似乎他们在Python 3中取消了通过删除快速加载脚本的所有简单方法 execfile()
有没有一个明显的选择我错过了?
根据文档,而不是
execfile("./filename")
使用
exec(open("./filename").read())
看到:
Python 3.0中有什么新功能
您应该自己阅读文件并执行代码.2to3当前替换
execfile("somefile.py", global_vars, local_vars)
如
with open("somefile.py") as f: code = compile(f.read(), "somefile.py", 'exec') exec(code, global_vars, local_vars)
(编译调用不是严格需要的,但它将文件名与代码对象相关联,使调试更容易一些.)
看到:
http://docs.python.org/release/2.7.3/library/functions.html#execfile
http://docs.python.org/release/3.2.3/library/functions.html#compile
http://docs.python.org/release/3.2.3/library/functions.html#exec
虽然exec(open("filename").read())
通常作为替代方案execfile("filename")
,但它错过了execfile
支持的重要细节.
Python3.x的以下函数尽可能与直接执行文件具有相同的行为.匹配运行python /path/to/somefile.py
.
def execfile(filepath, globals=None, locals=None):
if globals is None:
globals = {}
globals.update({
"__file__": filepath,
"__name__": "__main__",
})
with open(filepath, 'rb') as file:
exec(compile(file.read(), filepath, 'exec'), globals, locals)
# execute the file
execfile("/path/to/somefile.py")
笔记:
使用二进制读取来避免编码问题
保证关闭文件(Python3.x警告这个)
定义__main__
,一些脚本依赖于此来检查它们是否作为模块加载,例如.if __name__ == "__main__"
__file__
异常消息的设置更好,一些脚本用于__file__
获取相对于它们的其他文件的路径.
采用可选的全局变量和局部变量参数,并将其原样修改execfile
- 因此您可以通过在运行后读回变量来访问定义的任何变量.
不同于Python2的execfile
这并没有修改默认的当前命名空间.为此你必须明确传入globals()
&locals()
.
正如最近在python-dev邮件列表中所建议的那样,runpy模块可能是一个可行的选择.引用该消息:
https://docs.python.org/3/library/runpy.html#runpy.run_path
import runpy file_globals = runpy.run_path("file.py")
有一些细微差别execfile
:
run_path
总是创建一个新的命名空间 它将代码作为模块执行,因此全局变量和局部变量之间没有区别(这就是为什么只有一个init_globals
参数).全局变量返回.
execfile
在当前命名空间或给定命名空间中执行.locals
和globals
(如果给出)的语义类似于类定义中的locals和globals.
run_path
不仅可以执行文件,还可以执行鸡蛋和目录(有关详细信息,请参阅其文档).
这个更好,因为它接受来自调用者的全局变量和本地变量:
import sys def execfile(filename, globals=None, locals=None): if globals is None: globals = sys._getframe(1).f_globals if locals is None: locals = sys._getframe(1).f_locals with open(filename, "r") as fh: exec(fh.read()+"\n", globals, locals)
你可以编写自己的函数:
def xfile(afile, globalz=None, localz=None): with open(afile, "r") as fh: exec(fh.read(), globalz, localz)
如果你真的需要...
如果要加载的脚本与您运行的脚本位于同一目录中,那么"import"可能会完成这项工作吗?
如果需要动态导入代码,内置函数__ import__和模块imp值得关注.
>>> import sys >>> sys.path = ['/path/to/script'] + sys.path >>> __import__('test')>>> __import__('test').run() 'Hello world!'
test.py:
def run(): return "Hello world!"
如果您使用的是Python 3.1或更高版本,则还应该查看importlib.
这就是我所拥有的(file
在两个示例中已经分配给包含源代码的文件的路径):
execfile(file)
这是我用它取代的:
exec(compile(open(file).read(), file, 'exec'))
我最喜欢的部分:第二个版本在Python 2和3中都运行得很好,这意味着没有必要添加依赖于版本的逻辑.
请注意,如果您使用的不是ascii或utf-8的PEP-263编码声明,则上述模式将失败.您需要找到数据的编码,并在将其传递给exec()之前对其进行正确编码.
class python3Execfile(object): def _get_file_encoding(self, filename): with open(filename, 'rb') as fp: try: return tokenize.detect_encoding(fp.readline)[0] except SyntaxError: return "utf-8" def my_execfile(filename): globals['__file__'] = filename with open(filename, 'r', encoding=self._get_file_encoding(filename)) as fp: contents = fp.read() if not contents.endswith("\n"): # http://bugs.python.org/issue10204 contents += "\n" exec(contents, globals, globals)