Python: 'import *' vs execfile



在我的一些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

这两种方法都能按预期工作,但我很好奇我是否错过了任何gotchas,以及通常更推荐哪种方法以及为什么。

每次评估设置文件时,使用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在很大程度上是"约定而非配置"。遵守惯例。

另一个区别是: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 *

失败。

然而,

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

正常并导致d=={'x':1, 'z':2}

注意

x=1
execfile( 'dont_do_this.py' )

是OK并且导致变量CCD_ 18被添加到全局。

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

最新更新