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

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


当前回答

虽然exec(open("filename").read())通常作为execfile("filename")的替代,但它忽略了execfile支持的重要细节。

下面是Python3的函数。x是我能得到的与直接执行文件相同的行为。匹配运行python /path/到/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")

注:

Uses binary file reading to avoid encoding issues. Guaranteed to close the file (Python3.x warns about this). Defines __main__, some scripts depend on this to check if they are loading as a module or not for eg. if __name__ == "__main__". Setting __file__ is nicer for exception messages and some scripts use __file__ to get the paths of other files relative to them. Takes optional globals & locals arguments, modifying them in-place as execfile does - so you can access any variables defined by reading back the variables after running. Unlike Python2's execfile this does not modify the current namespace by default. For that you have to explicitly pass in globals() & locals().

其他回答

如果可以,请避免使用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”就可以了?

如果你需要动态导入代码,内置函数__ 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。

你可以写自己的函数:

def xfile(afile, globalz=None, localz=None):
    with open(afile, "r") as fh:
        exec(fh.read(), globalz, localz)

如果你真的需要…

我在这里只是个新手,所以如果我发现这个,可能纯粹是运气:

尝试运行脚本后,从解释器提示>>>与命令

    execfile('filename.py')

为此我得到了一个“NameError: name 'execfile' is not defined”,我尝试了一个非常基本的

    import filename

它工作得很好:-)

我希望这能对你有所帮助,感谢大家提供的提示、示例和所有那些对新手有很大启发的注释代码!

我使用Ubuntu 16.014 LTS x64。Python 3.5.2(默认,2016年11月17日17:05:23) [GCC 5.4.0 20160609

虽然exec(open("filename").read())通常作为execfile("filename")的替代,但它忽略了execfile支持的重要细节。

下面是Python3的函数。x是我能得到的与直接执行文件相同的行为。匹配运行python /path/到/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")

注:

Uses binary file reading to avoid encoding issues. Guaranteed to close the file (Python3.x warns about this). Defines __main__, some scripts depend on this to check if they are loading as a module or not for eg. if __name__ == "__main__". Setting __file__ is nicer for exception messages and some scripts use __file__ to get the paths of other files relative to them. Takes optional globals & locals arguments, modifying them in-place as execfile does - so you can access any variables defined by reading back the variables after running. Unlike Python2's execfile this does not modify the current namespace by default. For that you have to explicitly pass in globals() & locals().