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

两者都按预期工作,但我很好奇我是否遗漏了任何问题,一般来说哪种方法更推荐以及为什么。

4

3 回答 3

14

execfile每次评估设置文件时,使用函数将导致评估 Python 源文件 (.py)。您每次都在执行 Python 解析器。使用import不一定会这样做(可能使用 .pyc 文件)。通常,当您第一次在 Python(至少是 cPython)中运行项目时,它会被编译为字节码,并且不会再次重新编译。你打破了这一点。这不一定是问题,但您应该意识到这一点。

使用execfile还会导致您在文件中可能拥有的所有导入在settings_local.py文件的模块范围内重新评估settings.py。使用import *将包括settings_local.py模块范围内的所有项目。最终效果是相同的(包含在settings_local.py模块范围内的所有项目都包含在 中settings.py),但方法不同。

最后,模块作为模块执行而不是包含在内是正常的。代码包含诸如os.path.dirname(__file__). 如果任何代码确实使用了它,您会混淆它,因为代码将不再在作者可能合理预期的模块中执行。

根据我的经验,人们使用importnot execfile。Django 非常“约定优于配置”。遵守约定。

于 2012-07-28T19:12:09.843 回答
8

另一个区别: 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' )

没问题,并导致变量z被添加到全局变量中。

于 2012-11-02T17:57:32.937 回答
2

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

于 2012-07-28T17:52:04.523 回答