Python 3 中 execfile 的替代品是什么?
-
22-07-2019 - |
题
看来他们在 Python 3 中取消了通过删除快速加载脚本的所有简单方法 execfile()
我缺少明显的替代方案吗?
解决方案
其他提示
您只需阅读该文件并自己执行代码即可。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)
(编译调用并不是严格需要的,但它将文件名与代码对象关联起来,使调试更容易一些。)
看:
尽管 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 上建议 最近的邮件列表 奔跑的 模块可能是一个可行的替代方案。引用该消息:
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
, ,如果给定的话,类似于类定义中的局部变量和全局变量。run_path
不仅可以执行文件,还可以执行eggs和目录(具体参考其文档)。
这是一个较好的,因为它需要在全局和本地居民从呼叫者:
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 sys
>>> sys.path = ['/path/to/script'] + sys.path
>>> __import__('test')
<module 'test' from '/path/to/script/test.pyc'>
>>> __import__('test').run()
'Hello world!'
test.py:
def run():
return "Hello world!"
如果您正在使用Python 3.1或更高版本,你也应该看看的导入库。
下面是我有什么(file
已分配给该路径与在这两个例子中的源代码的文件):
execfile(file)
这就是我与取代它:
exec(compile(open(file).read(), file, 'exec'))
我最喜欢的部分:第二个版本工作在两个Python 2和3就好了,这意味着它没有必要在版本号的逻辑添加
。请注意,上述图案将如果您使用PEP-263编码声明失败 未ASCII或UTF-8。你需要找到的数据编码,并对其进行编码 正确之前递它给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)
另外,虽然不是一个纯Python的解决方案,如果你使用IPython的(或许你应该是这样),你可以这样做:
%run /path/to/filename.py
这是同样容易。
我在这里只是一个新手,所以也许它是纯粹的运气,如果我发现这一点:
尝试与命令运行从解释提示>>>脚本之后
execfile('filename.py')
针对我有一个“NameError:名称‘的execfile’没有定义”我试图一个非常基本的
import filename
它的工作良好: - )
我希望这可以帮助,并感谢大家的伟大的提示,实例和代码的所有精湛评论作品是对新手来说有很大的启发!
我使用Ubuntu 16.014 LTS 64。 的Python 3.5.2(默认情况下,2016年11月17日,17点05分23秒) [GCC 5.4.0 20160609]在Linux