Python:'import*'vs execfile

Ber*_*pac 11 python django python-import execfile django-settings

在我的一些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
Run Code Online (Sandbox Code Playgroud)

我最近发现了这个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
Run Code Online (Sandbox Code Playgroud)

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

Joe*_*Joe 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__).如果任何代码确实使用了这个,你会混淆它,因为代码将不再在作者可能合理预期的模块中执行.

根据我的经验,人们import不会使用execfile.Django非常"超越配置".遵循惯例.

  • `__file__`可以通过参数轻松提供.无论执行"导入模块"多少次,模块一次导入的主要区别是(每次调用时,`exec`执行文件),`import`不需要文件的显式路径(所以它也可以在zip存档中工作). (5认同)
  • 我发现有关execfile(而不是import)的一个优点是我可以动态地完成它.具体来说,如果我有一个设置模块列表,我可以在列表中循环,在每个模块上调用execfile.是否有办法用导入来做到这一点? (3认同)

Dav*_*ave 8

另一个区别:execfile获取上下文字典; 默认情况下的全局上下文或指定的字典.这可能会让一些奇怪的事情发生

dont_do_this.py:

# Probably not a good thing to do
z=x+1  # an expression that involves an un-defined field
Run Code Online (Sandbox Code Playgroud)

明显,

from dont_do_this import *
Run Code Online (Sandbox Code Playgroud)

失败.

然而,

d={'x':1}
execfile( 'dont_do_this.py', d )
Run Code Online (Sandbox Code Playgroud)

没问题就可以了 d=={'x':1, 'z':2}

注意

x=1
execfile( 'dont_do_this.py' )
Run Code Online (Sandbox Code Playgroud)

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