Python: "импорт *" против 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
Оба работают как задумано, но мне любопытно, пропускаю ли я какие-либо ошибки, и вообще, какой подход более рекомендуется и почему.
3 ответа
С помощью 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 - это "соглашение по конфигурации". Следуйте соглашению.
Еще одно отличие: 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
добавляются в глобалы.
Первая версия (from settings_local import *
) это то, что все ожидают увидеть. Это также позволит анализаторам кода найти модуль.