似乎他们在Python 3中取消了删除execfile()
我是否有一个明显的选择?
答案 0 :(得分:326)
答案 1 :(得分:201)
您应该自己阅读文件并执行代码。 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)
(编译调用不是严格需要的,但它将文件名与代码对象相关联,使调试更容易一些。)
请参阅:
答案 2 :(得分:56)
虽然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")
备注:强>
__main__
,某些脚本依赖于此来检查它们是否作为模块加载,例如。 if __name__ == "__main__"
__file__
对于异常消息更好,而某些脚本使用__file__
来获取与其相关的其他文件的路径。选择全局变量& locals参数,就像execfile
那样就地修改它们 - 所以你可以通过在运行后读回变量来访问任何定义的变量。
与Python2 execfile
不同,默认情况下不修改当前命名空间。为此,您必须明确传入globals()
& locals()
。
答案 3 :(得分:52)
最近作为suggested on the 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
不仅可以执行文件,还可以执行鸡蛋和目录(有关详细信息,请参阅其文档)。
答案 4 :(得分:18)
您可以编写自己的函数:
def xfile(afile, globalz=None, localz=None):
with open(afile, "r") as fh:
exec(fh.read(), globalz, localz)
如果你真的需要......
答案 5 :(得分:17)
这个更好,因为它接受来自调用者的全局变量和本地变量:
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)
答案 6 :(得分:11)
如果您要加载的脚本与您运行的脚本位于同一目录中,那么“import”可能会完成这项工作吗?
如果您需要动态导入代码,内置函数__ 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!'
test.py:
def run():
return "Hello world!"
如果您使用的是Python 3.1或更高版本,则还应该查看importlib。
答案 7 :(得分:8)
这里有我的内容(file
已经分配到文件的路径,并在两个示例中都包含源代码):
execfile(file)
这是我用以下内容替换它:
exec(compile(open(file).read(), file, 'exec'))
我最喜欢的部分:第二版在Python 2和3中都运行得很好,这意味着它不需要添加依赖于版本的逻辑。
答案 8 :(得分:5)
请注意,如果您使用的是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)
答案 9 :(得分:3)
此外,虽然不是纯粹的Python解决方案,但如果您正在使用IPython(无论如何应该如此),您可以这样做:
%run /path/to/filename.py
这同样容易。
答案 10 :(得分:1)
我只是一个新手,所以如果我发现这个可能是纯粹的运气:
尝试从解释器提示符&gt;&gt;&gt;运行脚本后使用命令
execfile('filename.py')
我得到了一个“NameError:name'execfile'没有定义”我尝试了一个非常基本的
import filename
效果很好: - )
我希望这对您有所帮助,并感谢大家提供的精彩提示,示例和所有精心评论的代码,这对新手来说是一个很好的灵感!
我使用的是Ubuntu 16.014 LTS x64。 Python 3.5.2(默认,2016年11月17日,17:05:23) Linux上的[GCC 5.4.0 20160609]
答案 11 :(得分:1)
请尽量避免使用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
关键字一次。