Могу ли я использовать __init__.py для определения глобальных переменных?

Я хочу определить константу, которая должна быть доступна во всех подмодулях пакета. Я думал, что лучшее место будет в файле __init__.py корневого пакета. Но я не знаю, как это сделать. Предположим, у меня есть несколько подпакетов и каждый с несколькими модулями. Как я могу получить доступ к этой переменной из этих модулей?

Конечно, если это совершенно неправильно, и есть лучшая альтернатива, я бы хотел это знать.

Ответ 1

Вы можете разместить их в __init__.py. Это делается все время.

mypackage/__init__.py

MY_CONSTANT = 42

mypackage/mymodule.py

from mypackage import MY_CONSTANT
print "my constant is", MY_CONSTANT

Затем импортируйте mymodule:

>>> from mypackage import mymodule
my constant is 42

Тем не менее, если у вас есть константы, было бы разумно (лучше всего, вероятно) разместить их в отдельном модуле (constants.py, config.py,...), а затем, если вы хотите, чтобы они были в пакете namespace, импортируйте их.

mypackage/__init__.py

from mypackage.constants import *

Тем не менее, это не включает автоматически константы в пространствах имен модулей пакета. Каждому модулю в пакете все равно придется импортировать константы явно либо из mypackage, либо из mypackage.constants.

Ответ 2

Вы не можете этого сделать. Вам придется явно импортировать свои константы в каждое пространство имен отдельных модулей. Лучший способ достичь этого - определить ваши константы в модуле "config" и импортировать его везде, где вам это нужно:

# mypackage/config.py
MY_CONST = 17

# mypackage/main.py
from mypackage.config import *

Ответ 3

Вы можете определить глобальные переменные из любого места, но это действительно плохая идея. импортируйте модуль __builtin__ и измените или добавьте атрибуты к этим модулям, и вдруг у вас появятся новые встроенные константы или функции. Фактически, когда мое приложение устанавливает gettext, я получаю функцию _() во всех моих модулях, не импортируя ничего. Таким образом, это возможно, но, конечно, только для проектов типа приложений, а не для многоразовых пакетов или модулей.

И я думаю, никто не рекомендовал бы эту практику в любом случае. Что не так с пространством имен? У упомянутого приложения есть модуль версии, так что у меня есть глобальные переменные, доступные как version.VERSION, version.PACKAGE_NAME и т.д.

Ответ 4

Просто хотелось добавить, что константы могут быть использованы с помощью файла config.ini и проанализированы в script с помощью библиотеки configparser. Таким образом, у вас могут быть константы при нескольких обстоятельствах. Например, если у вас есть константы параметров для двух отдельных запросов URL, просто назовите их так:

mymodule/config.ini
[request0]
conn = '[email protected]'
pass = 'admin'
...

[request1]
conn = '[email protected]'
pass = 'dinosaur'
...

Я нашел документацию на веб-сайте Python очень полезной. Я не уверен, существуют ли какие-либо различия между Python 2 и 3, поэтому ссылки на них:

Для Python 3: https://docs.python.org/3/library/configparser.html#module-configparser

Для Python 2: https://docs.python.org/2/library/configparser.html#module-configparser