Подтвердить что ты не робот

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

Оба работают по назначению, но мне любопытно, не хватает ли я каких-либо ошибок, и вообще какой подход более рекомендуется и почему.

4b9b3361

Ответ 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 not execfile. Django очень "согласуется с конфигурацией". Следуйте за соглашением.

Ответ 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 *) - это то, что все ожидали бы увидеть. Он также позволит анализаторам кода найти модуль.