Python 3 中 execfile 的替代品是什么?
- 2024-12-09 08:30:00
- admin 原创
- 168
问题描述:
看来他们在 Python 3 中通过删除取消了所有快速加载脚本的简便方法execfile()
。
我是否遗漏了其他明显的替代方案?
解决方案 1:
根据文档,而不是
execfile("./filename")
使用
exec(open("./filename").read())
看:
Python 3.0 中的新功能
execfile
exec
解决方案 2:
你只需要自己读取文件并执行代码。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
解决方案 3:
虽然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()
。
解决方案 4:
正如最近在 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`如果给出)类似于类定义中的局部和全局。
run_path
不仅可以执行文件,还可以执行eggs和目录(详情请参阅其文档)。
解决方案 5:
这个更好,因为它从调用者那里获取全局变量和本地变量:
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()+"
", globals, locals)
解决方案 6:
你可以编写自己的函数:
def xfile(afile, globalz=None, localz=None):
with open(afile, "r") as fh:
exec(fh.read(), globalz, localz)
如果你真的需要...
解决方案 7:
如果您要加载的脚本与您运行的脚本位于同一目录中,也许“导入”可以完成这项工作?
如果您需要动态导入代码,内置函数__ import__和模块imp值得一看。
>>> import sys
>>> sys.path = ['/path/to/script'] + sys.path
>>> __import__('test')
<module 'test' from '/path/to/script/test.pyc'>
>>> __import__('test').run()
'Hello world!'
测试.py:
def run():
return "Hello world!"
如果您使用的是 Python 3.1 或更高版本,您还应该查看importlib。
解决方案 8:
这是我所得到的(file
在两个示例中都已分配给包含源代码的文件的路径):
execfile(file)
这是我将其替换为的内容:
exec(compile(open(file).read(), file, 'exec'))
我最喜欢的部分:第二个版本在 Python 2 和 3 中都能很好地运行,这意味着不需要添加与版本相关的逻辑。
解决方案 9:
尽量避免exec()
。对于大多数应用程序来说,使用 Python 的导入系统更为简洁。
该函数使用内置函数importlib
将文件作为实际模块执行:
from importlib import util
def load_file_as_module(name, location):
spec = util.spec_from_file_location(name, location)
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
使用示例
我们有一个文件foo.py
:
def hello():
return 'hi from module!'
print('imported from', __file__, 'as', __name__)
并将其作为常规模块导入:
>>> mod = load_file_as_module('mymodule', './foo.py')
imported from /tmp/foo.py as mymodule
>>> mod.hello()
hi from module!
>>> type(mod)
<class 'module'>
优点
这种方法不会污染命名空间或干扰您的,$PATH
而exec()
直接在当前函数的上下文中运行代码,可能会导致名称冲突。此外,模块属性(如__file__
和)__name__
将正确设置,并且代码位置将保留。因此,如果您附加了调试器或模块引发异常,您将获得可用的回溯。
请注意,与静态导入的一个小区别是,每次运行时都会导入(执行)模块load_file_as_module()
,而不仅仅是使用import
关键字时导入(执行)一次。
解决方案 10:
请注意,如果您使用的 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("
"):
# http://bugs.python.org/issue10204
contents += "
"
exec(contents, globals, globals)
解决方案 11:
此外,虽然这不是一个纯 Python 解决方案,但如果您使用 IPython(您可能应该使用),您可以执行以下操作:
%run /path/to/filename.py
这同样容易。
解决方案 12:
我只是这里的新手,所以如果我发现这个也许纯粹是运气好:
尝试使用命令从解释器提示符 >>> 运行脚本后
execfile('filename.py')
我得到了一个“NameError:名称‘execfile’未定义”我尝试了一个非常基本的
import filename
效果很好:-)
我希望这可以有所帮助,并感谢大家提供的出色提示、示例和所有那些对新手有很大启发的精彩代码片段!
我在 Linux 上使用 Ubuntu 16.014 LTS x64。Python 3.5.2(默认,2016 年 11 月 17 日,17:05:23)[GCC 5.4.0 20160609]