import和execfile的区别

7

我有一个文件utils.py,其中包含一个名为f1()的函数。

从另一个Python脚本中,我可以使用import utilsexecfile('utils.py')并访问f1()。这两种方法之间有什么区别?

1个回答

7

有很多差异,但从您的角度来看,最重要的可能是 import 能够更好地控制 utils.py 中定义的对象所在的命名空间。

让我们考虑三种不同的 import 变体。首先是您提问的这种情况:

import utils
utils.f1()

utils 是唯一添加到您工作空间中的符号——任何预先存在于基础工作空间中的f1都不会被覆盖,如果没有,则单独使用f1()将不被识别。 对于我打算维护的代码,我非常喜欢这种导入方式,因为它使我能够轻松搜索源文件,找出它依赖于utils的所有位置。

但是,如果每次都说utils.f1()太冗长,那么您可以这样做:

from utils import f1
f1()

现在,如果你写f1(),那么它将调用utils.f1(),因为现在你已经将这个代码对象与工作区中的名称f1相关联了。现在稍微难以概述你的代码依赖于utils模块的情况。但至少这种类型的import语句可以让你精确控制哪些符号被导入,哪些不被导入。你甚至可以在此过程中重命名符号:
from utils import f1 as EffOne
EffOne()  

最后,您可以选择完全失去对命名空间的控制:

from utils import *

现在,谁知道已经导入了哪些符号:基本上所有 utils 提供给世界的一切(或者如果 utils 的开发人员费心指定了一个 __all__ 属性,那么只有列在其中的一切)。我建议你仅在快速粗糙的编程时使用 import *,如果必须使用的话。
实际上,这种导入样式从名称空间的角度来看最接近 execfileexecfile('utils.py') 做的事情与 from utils import * 几乎相同,因为它会将 utils 定义的所有符号不加思索地倾泻到你的工作区中。唯一的区别是,如果定义了 __all__execfile 甚至不会将自己限制于其中的符号,事实上, __all__ 符号本身将与其他所有内容一起倾泻在你的膝盖上。
除了命名空间之外,from utils import *execfile('utils.py') 之间仍然有很多区别。其中之一是缓存:对 utils 的第二个 import 调用将非常快(代码不会重新运行),但第二个调用 execfile('utils.py') 可能与第一个一样慢,因为代码将被重新运行。此外,可能存在一些代码(通常是测试代码)在 utils.py 中,作者并不希望在导入时运行,而是只有当文件通过 execfile 执行时才运行。这样的代码放在一个 if __name__ == '__main__': 子句中。

execfile 已死 - exec(open('utils.py').read()) 长存,以及 IPython 的 %run utils。https://dev59.com/YHRC5IYBdhLWcg3wAcbU/ - jez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接