如果您可以覆盖 builtins.__import__ 和一个简单的正则表达式来转换没有括号的打印语句,那么您可以执行以下操作。请注意,这实际上不会更改任何文件,只是当您导入它们时,它会将代码读入字符串,调整该字符串,然后将固定代码发送到编译器/导入器
import re
import sys
if sys.version_info >= (3, 0):
import lib2to3
from lib2to3 import main, refactor
import os
import types
import builtins
import sys
import importlib
cache = {}
prevImport = builtins.__import__
def customImport(path, *args, **kwargs):
#print (path, args, kwargs)
try:
return fimport(path + ".py")
except:
return prevImport(path, *args, **kwargs)
def reload(filename):
fimport(filename.__file__, forceReload=True)
def fimport(filename, forceReload=False):
filename = os.path.abspath(filename)
modulePath = os.path.splitext(os.path.basename(filename))[0]
if filename in cache and not forceReload:
execval, modifyTime, module = cache[filename]
if modifyTime == os.path.getmtime(filename):
return module
f = open(filename)
text = f.read() + "\n"
p = re.compile("print")
res = []
curI = 0
for m in p.finditer(text):
i = m.start()
res.append(text[curI:i])
curI = i
pieceTmp = text[i:].split("\n")[0]
piece = text[i:].split("\n")[0].split("#")[0]
pieceAfter = piece[len('print'):].strip()
if pieceAfter[0] != '(':
resLine = "print" + "(" + pieceAfter + ")" + "\n"
res.append(resLine)
else:
res.append(pieceTmp)
curI += len(pieceTmp)+1
text = "".join(res)
f.close()
'''
# this code can run lib2to3 if you want but just for replacing prints that is not needed
#fixes = sorted(lib2to3.refactor.get_fixers_from_package('lib2to3.fixes'))
fixes = ['lib2to3.fixes.fix_print']
rt = lib2to3.main.StdoutRefactoringTool(fixes, {}, [], False, False)
res = str(rt.refactor_string(text, name=modulePath))
'''
res = text
res = compile(res, '<string>', 'exec')
module = types.ModuleType(modulePath)
module.__file__ = filename
cache[filename] = (res, os.path.getmtime(filename), module)
exec(res, module.__dict__)
return module
builtins.__import__ = customImport
importlib.reload = reload
如果您将此代码保存到,例如,pastimport.py,那么假设我有一个名为 juniper.py 的文件:
def wow(a):
print a
现在如果我想从 python3 调用 juniper.py,我可以这样做
import pastimport
import juniper
juniper.wow("bean")
它会运行:)
这可能会更快,更像是典型的带有缓存和日志记录等的导入,但我还不完全了解 pyc 文件的生成方式和时间。 c插件也可能存在边缘情况,我不确定。因此,请随意提出改进建议,但至少这是一个概念证明。我认为您应该能够实际调整解释器输入和当前文件的值,但我现在正在摆弄。
从技术上讲,这还允许您导入任何 python2 文件(2to3 修复 xrange、print 等),如果这些文件导入其他 python2 文件,它们也会被转换,因为这会覆盖每个人都使用的导入。您还可以实现任意运算符重载、需要静态类型、实际上需要大括号,从技术上讲,甚至可以从其他语言导入代码或通过这个单一导入完全更改 python。但我离题了