Don*_*kby 7 python python-2.7 python-3.x
我exec在一些Python 2代码中使用该语句,并且我试图使该代码与Python 2和Python 3兼容,但是在Python 3中,exec已经从语句变为函数.是否可以编写与Python 2和3兼容的代码?我已经阅读了Python 2和Python 3双重开发,但我对exec语句/函数更改的特定解决方案感兴趣.
我意识到这exec通常是气馁的,但我正在构建一个Eclipse插件,它在PyDev之上实现了实时编码.有关详细信息,请参阅项目页面.
Ant*_*ala 12
一些Python移植指南exec 错误:
如果你需要传入全局或本地词典,你需要定义一个带有两个不同实现的自定义函数,一个用于Python 2,另一个用于Python 3.通常
six包括一个很好的实现exec_().
将Python 2代码移植到Python 3(*)中不需要这样的自定义函数.你可以做exec(code),exec(code, globs)而且exec(code, globs, locs)在Python 2,和它的作品.
Python已经永远接受的Python 3兼容的"语法"的exec,只要是exec存在的.这样做的原因是Python 2和Python 1(?!)有一个hack 与Python 0.9.8 保持向后兼容,这exec是一个函数.现在,如果exec传递一个2元组,则将其解释为(code, globals),如果是3元组,则将其解释为(code, globals, locals).是的,exec_insix是不必要的复杂.
从而,
exec(source, global_vars, local_vars)
Run Code Online (Sandbox Code Playgroud)
保证在CPython 0.9.9,1.x,2.x,3.x中以相同的方式工作; 我还验证了它适用于Jython 2.5.2,PyPy 2.3.1(Python 2.7.6)和IronPython 2.6.1:
Jython 2.5.2 (Release_2_5_2:7206, Mar 2 2011, 23:12:06)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_25
Type "help", "copyright", "credits" or "license" for more information.
>>> exec('print a', globals(), {'a':42})
42
Run Code Online (Sandbox Code Playgroud)
*)存在细微差别,因此并非所有Python 3代码都适用于Python 2,即
foo = exec在Python 3中有效,但在Python 2中没有,所以也是如此map(exec, ['print(a + a)', 'print(b + b)']),但我真的不知道为什么有人想在实际代码中使用这些结构.正如Paul Hounshell在Python 2中所发现的,以下代码将引发SyntaxError:函数'print_arg'中不允许使用非限定exec,因为它包含带有自由变量的嵌套函数:
def print_arg(arg):
def do_print():
print(arg)
exec('do_print()')
Run Code Online (Sandbox Code Playgroud)
以下构造无一例外地起作用.
def print_arg(arg):
def do_print():
print(arg)
exec 'do_print()' in {}
Run Code Online (Sandbox Code Playgroud)
在Python 2.7.9之前,如果用于exec('do_print()', {})后者,则会抛出相同的SyntaxError; 但是从Python 2.7.9开始,解析器/编译器也会允许这种备用元组语法.
同样,边缘情况下的解决方案可能是放弃使用exec和使用eval(eval可用于执行compile在exec模式下编译的字节码):
def print_arg(arg):
def do_print():
print(arg)
eval(compile('do_print(); print("it really works")', '<string>', 'exec'))
Run Code Online (Sandbox Code Playgroud)
我已经写就的内部更详细的解答exec,eval并compile就什么是EVAL,EXEC之间的差异,在Python编写?
在Antti发布他的回答说Python 2支持Python 3 exec函数语法之前,我找到了几个选项.
第一个表达式也可以是长度为2或3的元组.在这种情况下,必须省略可选部分.表格
exec(expr, globals)相当于exec expr in globals,而形式exec(expr, globals, locals)相当于exec expr in globals, locals.exec的元组形式提供与Python 3的兼容性,其中exec是函数而不是语句.
如果由于某种原因你不想使用它,这里是我找到的所有其他选项.
导入存根
您可以声明两个不同的导入存根,并导入与当前解释器一起使用的任何导入存根.这基于我在PyDev源代码中看到的内容.
这是你放在主模块中的内容:
try:
from exec_python2 import exec_code #@UnusedImport
except:
from exec_python3 import exec_code #@Reimport
Run Code Online (Sandbox Code Playgroud)
这是你输入的内容exec_python2.py:
def exec_code(source, global_vars, local_vars):
exec source in global_vars, local_vars
Run Code Online (Sandbox Code Playgroud)
这是你输入的内容exec_python3.py:
def exec_code(source, global_vars, local_vars):
exec(source, global_vars, local_vars)
Run Code Online (Sandbox Code Playgroud)
执行Eval
Ned Batchelder发布了一种技术,可以exec在调用中包装语句,eval因此它不会在Python 3中导致语法错误.它很聪明,但不清楚.
# Exec is a statement in Py2, a function in Py3
if sys.hexversion > 0x03000000:
def exec_function(source, filename, global_map):
"""A wrapper around exec()."""
exec(compile(source, filename, "exec"), global_map)
else:
# OK, this is pretty gross. In Py2, exec was a statement, but that will
# be a syntax error if we try to put it in a Py3 file, even if it isn't
# executed. So hide it inside an evaluated string literal instead.
eval(compile("""\
def exec_function(source, filename, global_map):
exec compile(source, filename, "exec") in global_map
""",
"<exec_function>", "exec"
))
Run Code Online (Sandbox Code Playgroud)
六包
该6包是用于编写代码的兼容性库,都将Python 2和Python 3的下运行它有一个exec_()功能,这相当于两个版本.我没试过.
| 归档时间: |
|
| 查看次数: |
969 次 |
| 最近记录: |