似乎他们取消了在Python 3中通过删除execfile()快速加载脚本的所有简单方法

我是否错过了一个明显的选择?


当前回答

如果可以,请避免使用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关键字那样只导入一次。

其他回答

这个更好,因为它从调用者那里获取全局变量和局部变量:

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')
<module 'test' from '/path/to/script/test.pyc'>
>>> __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中都工作得很好,这意味着不需要添加版本相关的逻辑。

您只需读取文件并自己执行代码。2to3电流替换

execfile("somefile.py", global_vars, local_vars)

as

with open("somefile.py") as f:
    code = compile(f.read(), "somefile.py", 'exec')
    exec(code, global_vars, local_vars)

(并不严格需要compile调用,但它将文件名与code对象关联起来,使调试更容易一些。)

See:

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