Python 3 中代替 execfile 的方法是什么?

69
4个回答

77

2to3 脚本会替换

execfile(filename, globals, locals)

exec(compile(open(filename, "rb").read(), filename, 'exec'), globals, locals)

这似乎是官方推荐。您可能希望使用with块来确保文件及时关闭:

with open(filename, "rb") as source_file:
    code = compile(source_file.read(), filename, "exec")
exec(code, globals, locals)
你可以省略globalslocals参数以在当前作用域中执行文件,或者使用exec(code,{})来使用新的临时字典作为全局和局部字典,有效地在新的临时作用域中执行文件。

3
为什么这个版本比Lennart的版本更好? - Matt Joiner
1
@SvenMarnach,如果您可以发布官方建议或源代码的链接(以便人们可以确保它不会在未来被“修复”),我会给它一个+1。=) - anatoly techtonik
1
@kenorb:它在Python 3.4中确实有效。您显然尝试使用最后一行而没有替换“locals”和“globals”,并用您想要的任何内容代替它们。它们只是占位符,我不知道您想要传递什么,或者是否要完全省略它们。我认为这是“官方”的建议,因为这是“官方”的2to3工具迁移execfile()调用的方式。 - Sven Marnach
1
@vinaygarg 这些是包含全局和局部变量的字典,文件应在其中执行。您可以省略它们以在当前范围内执行文件。常见的替代方法是使用 exec(..., {}) 在新的临时范围内执行文件。 - Sven Marnach
1
@AidasBendoraitis 我在这里使用了 globalslocals 作为变量名;我也可以使用 xy 或其他任何变量名。通常情况下,你不会使用 exec(code, globals(), locals()),因为这与仅使用 exec(code) 是相同的。 - Sven Marnach
显示剩余15条评论

68
execfile(filename)

可以被替换为

exec(open(filename).read())

这适用于所有版本的Python。

较新版本的Python将会警告您没有关闭该文件,所以如果您想消除那个警告,可以执行以下操作:

with open(filename) as infile:
    exec(infile.read())

但实际上,如果你关心关闭文件,就应该足够关注,不要在首次使用exec


1
这个版本为什么比Sven的版本更好? - Matt Joiner
17
@Matt:更简单? - Lennart Regebro
1
在Python 2.x中,你需要使用exec ... in ...的形式来执行这种情况下的exec。例如,exec code in globals() 将会在模块的全局命名空间中执行代码。请注意,被执行的代码无法可靠地改变嵌套函数中可见的局部变量。 - Sven Marnach
2
@VPeric:这里所有的东西都是有效的,如果您有特定问题,请将其转化为问题。 - Lennart Regebro
1
不需要,它会在垃圾回收时关闭,所以不必关闭它(尽管关闭它是个好主意)。 - Lennart Regebro
显示剩余9条评论

9
在Python3.x中,这是我能想到的最接近直接执行文件的方法,与运行python /path/to/somefile.py相匹配。
注意:
  • 使用二进制读取以避免编码问题
  • 保证关闭文件(Python3.x会发出警告)
  • 定义__main__,一些脚本依赖于此来检查它们是否作为模块加载,例如:if __name__ == "__main__"
  • 设置__file__可以使异常消息更好,并且一些脚本使用__file__来获取相对于它们的其他文件的路径。
def exec_full(filepath):
    global_namespace = {
        "__file__": filepath,
        "__name__": "__main__",
    }
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), global_namespace)

# Execute the file.
exec_full("/path/to/somefile.py")

我有这个旧版本:execfile(join(dirname(__file__), 'ExcelLibrary', 'version.py')),那么在新版本中应该怎么写呢? exec(open(filename).read()) - tijnn
@tijnn 这不容易在一行内完成,这就是为什么我提供了一个函数 - exec_full - ideasman42

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接