【问题标题】:Python: 'import *' vs execfilePython:'import *' vs execfile
【发布时间】:2012-07-27 01:09:36
【问题描述】:

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

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

【问题讨论】:

    标签: python django django-settings python-import execfile


    【解决方案1】:

    使用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__) 之类的内容是合理的。如果任何代码确实使用了它,您会混淆它,因为代码将不再在作者可能合理预期的模块中执行。

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

    【讨论】:

    • __file__ 可以通过参数轻松提供。主要区别在于,无论import module 执行多少次(exec 每次调用时都会执行文件),模块只导入一次,而import 不需要文件的显式路径(所以它也可以在 zip 存档中工作)。
    • @J.F.Sebastian 这应该是一个答案。
    • 我发现关于 execfile(相对于导入)的一个优点是我可以动态地执行它。具体来说,如果我有一个设置模块列表,我可以在列表中循环,在每个模块上调用 execfile。有没有办法用 import 代替?
    • 你为什么要动态地做呢?您的部署可能有多复杂?
    • 即导入使用sys.modules缓存来避免重新导入已经导入的模块。
    【解决方案2】:

    另一个区别: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 被添加到全局变量中。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2015-02-15
        • 2018-12-09
        • 2014-04-19
        • 2011-04-02
        • 2010-11-18
        • 2023-03-07
        • 2014-04-21
        • 2017-02-24
        • 2010-10-29
        相关资源
        最近更新 更多