问题:python 3中execfile的替代方法是什么?

看来他们在Python 3中取消了通过删除以下命令快速加载脚本的所有简便方法 execfile()

我是否有明显的替代品?

It seems they canceled in Python 3 all the easy way to quickly load a script by removing execfile()

Is there an obvious alternative I’m missing?


回答 0

根据文档,而不是

execfile("./filename") 

采用

exec(open("./filename").read())

看到:

According to the documentation, instead of

execfile("./filename") 

Use

exec(open("./filename").read())

See:


回答 1

您只应该自己读取文件并执行代码。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)

(并非严格要求进行编译调用,但是它将文件名与代码对象相关联,从而使调试更加容易。)

看到:

You are just supposed to read the file and exec the code yourself. 2to3 current replaces

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)

(The compile call isn’t strictly needed, but it associates the filename with the code object making debugging a little easier.)

See:


回答 2

尽管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__获取其他文件相对于它们的路径。
  • 接受可选的globals和locals参数,就地进行修改execfile-您可以在运行后通过读回变量来访问定义的任何变量。

  • 与Python2不同,execfile这默认情况下不会修改当前命名空间。为此,您必须显式传入globals()locals()

While exec(open("filename").read()) is often given as an alternative to execfile("filename"), it misses important details that execfile supported.

The following function for Python3.x is as close as I could get to having the same behavior as executing a file directly. That matches running 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")

Notes:

  • Uses binary 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().


回答 3

正如最近在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在当前命名空间或给定命名空间中执行。的语义localsglobals,如果给定的,类似于当地人和全局类定义中。

  • run_path 不仅可以执行文件,还可以执行蛋和目录(有关详细信息,请参阅其文档)。

As suggested on the python-dev mailinglist recently, the runpy module might be a viable alternative. Quoting from that message:

https://docs.python.org/3/library/runpy.html#runpy.run_path

import runpy
file_globals = runpy.run_path("file.py")

There are subtle differences to execfile:

  • run_path always creates a new namespace. It executes the code as a module, so there is no difference between globals and locals (which is why there is only a init_globals argument). The globals are returned.

    execfile executed in the current namespace or the given namespace. The semantics of locals and globals, if given, were similar to locals and globals inside a class definition.

  • run_path can not only execute files, but also eggs and directories (refer to its documentation for details).


回答 4

这是更好的方法,因为它从调用者那里获取了全局变量和本地变量:

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)

This one is better, since it takes the globals and locals from the caller:

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)

回答 5

您可以编写自己的函数:

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

如果您真的需要…

You could write your own function:

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

If you really needed to…


回答 6

如果要加载的脚本与运行的脚本位于同一目录中,则也许“ 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

If the script you want to load is in the same directory than the one you run, maybe “import” will do the job ?

If you need to dynamically import code the built-in function __ import__ and the module imp are worth looking at.

>>> 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!"

If you’re using Python 3.1 or later, you should also take a look at importlib.


回答 7

这就是我所拥有的(file两个示例中的源代码都已将其分配给文件的路径):

execfile(file)

这是我替换为的内容:

exec(compile(open(file).read(), file, 'exec'))

我最喜欢的部分:第二个版本在Python 2和3中都可以正常工作,这意味着不必添加依赖于版本的逻辑。

Here’s what I had (file is already assigned to the path to the file with the source code in both examples):

execfile(file)

Here’s what I replaced it with:

exec(compile(open(file).read(), file, 'exec'))

My favorite part: the second version works just fine in both Python 2 and 3, meaning it’s not necessary to add in version dependent logic.


回答 8

请注意,如果您使用的不是非ascii或utf-8的PEP-263编码声明,上述模式将失败。您需要找到数据的编码,并在将其交给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)

Note that the above pattern will fail if you’re using PEP-263 encoding declarations that aren’t ascii or utf-8. You need to find the encoding of the data, and encode it correctly before handing it to 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

另外,虽然不是纯粹的Python解决方案,但如果您使用的是IPython(无论如何也应该这样做),则可以执行以下操作:

%run /path/to/filename.py

这同样容易。

Also, while not a pure Python solution, if you’re using IPython (as you probably should anyway), you can do:

%run /path/to/filename.py

Which is equally easy.


回答 10

我只是这里的新手,所以如果发现了这个,也许纯粹是运气:

尝试使用命令从解释器提示符>>>运行脚本后

    execfile('filename.py')

为此,我得到了“ NameError:名称’execfile’未定义”,我尝试了一个非常基本的

    import filename

它运作良好:-)

我希望这会有所帮助,并感谢大家提供的出色提示,示例以及所有那些对新手有很大启发的精妙注释的代码!

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

I’m just a newbie here so maybe it’s pure luck if I found this :

After trying to run a script from the interpreter prompt >>> with the command

    execfile('filename.py')

for which I got a “NameError: name ‘execfile’ is not defined” I tried a very basic

    import filename

it worked well :-)

I hope this can be helpful and thank you all for the great hints, examples and all those masterly commented pieces of code that are a great inspiration for newcomers !

I use Ubuntu 16.014 LTS x64. Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux


回答 11

对我来说,最干净的方法是importlib按路径使用和导入文件作为模块,如下所示:

from importlib import util

def load_file(name, path):
    spec = util.spec_from_file_location(name, path)
    module = util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

使用范例

让我们有一个文件foo.py

print('i got imported')
def hello():
    print('hello from foo')

现在就像导入普通模块一样使用它:

>>> foo = load_file('foo', './foo.py')
i got imported
>>> foo.hello()
hello from foo

与直接方法相比,我更喜欢这种技术,exec(open(...))因为它不会使您的命名空间混乱或不必要地造成混乱$PATH

To me, the cleanest approach is to use importlib and import the file as a module by path, like so:

from importlib import util

def load_file(name, path):
    spec = util.spec_from_file_location(name, path)
    module = util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

Usage example

Let’s have a file foo.py:

print('i got imported')
def hello():
    print('hello from foo')

Now just import and use it like a normal module:

>>> foo = load_file('foo', './foo.py')
i got imported
>>> foo.hello()
hello from foo

I prefer this technique over direct approaches like exec(open(...)) because it does not clutter your namespaces or unnecessarily messes with $PATH.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。