Python:'import *'与execfile的区别

13

在我编写的一些 Django 应用程序中,我使用了一个 settings_local.py 文件来覆盖在不同环境(例如开发、测试和生产)中不同的设置。我最初使用了以下代码将其内容包含在 settings.py 中:

try:
    from settings_local import *
except ImportError:
    sys.stderr.write("The settings_local.py file is missing.\n")
    DEBUG=False

最近我发现了execfile函数,并转而使用以下代码:

try:
    execfile(path.join(PROJECT_ROOT, "settings_local.py"))
except IOError:
    sys.stderr.write("The settings_local.py file is missing.\n"
    DEBUG=False

两种方法都能正常工作,但我想知道是否有什么需要注意的点,以及一般来说哪种方法更推荐,为什么。

3个回答

14
使用execfile函数将导致每次评估设置文件时都会评估Python源文件(.py)。您每次执行Python解析器。使用import不一定会这样做(可能使用.pyc文件)。通常,在Python(至少是cPython)中第一次运行项目时,它会被编译为字节码,而不会再次被重新编译。您正在打破它。这不一定是个问题,但您应该意识到这一点。
使用execfile还会导致在settings.py模块范围内重新评估在settings_local.py文件中可能存在的所有导入。使用import *将包括settings_local.py模块范围内的所有项目。净效果相同(所有包含在settings_local.py模块范围内的项目都包含在settings.py中),但方法不同。
最后,模块作为模块而不是包含在代码中执行是很正常的。代码包括类似于os.path.dirname(__file__)这样的内容是合理的。如果任何代码使用了这个,你将会让它混淆,因为代码将不再在作者可以合理地期望的模块中执行。
根据我的经验,人们使用import而不是execfile。Django非常注重“约定优于配置”。跟随约定。

6
__file__可以通过参数轻松提供。主要区别在于,无论执行多少次import module,模块只被导入一次(每次调用exec时都会执行文件),而import不需要显式指定文件路径(因此它也可以在 zip 归档文件中工作)。 - jfs
@J.F.Sebastian 那应该就是一个答案。 - Marcin
3
相比于import,我发现execfile的一个优点是可以动态执行。具体来说,如果我有一个设置模块的列表,我可以循环遍历列表,并对每个模块调用execfile函数。那么使用import有没有办法实现类似的功能呢? - Berislav Lopac
为什么你想要动态地完成它呢?你的部署可能有多复杂? - Joe
具体来说,导入使用 sys.modules 缓存以避免重新导入已经被导入的模块。 - asmeurer

9
另一个不同点:execfile会得到一个上下文字典;默认为全局上下文或指定的字典。这可能会导致一些奇怪的事情发生。
dont_do_this.py:
# Probably not a good thing to do
z=x+1  # an expression that involves an un-defined field

显然,
from dont_do_this import *

fails.

However,

d={'x':1}
execfile( 'dont_do_this.py', d )

这样是可以的,并且结果为d=={'x':1, 'z':2}

注意

x=1
execfile( 'dont_do_this.py' )

运行正常,结果是变量z被添加到全局变量中。


2
第一个版本(from settings_local import *)是每个人都期望看到的。它还可以让代码分析器找到该模块。

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