我可以使用__init__.py定义全局变量吗?


130

我想定义一个常量,该常量应在包的所有子模块中可用。我以为最好的地方__init__.py在根包的文件中。但是我不知道该怎么做。假设我有几个子包,每个子包都有几个模块。如何从这些模块访问该变量?

当然,如果这是完全错误的,并且有更好的选择,我想知道。

Answers:


196

您应该能够将它们放入__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,...)中,然后将其放入包名称空间中是合理的(可能是最佳做法),然后导入他们。

mypackage/__init__.py

from mypackage.constants import *

尽管如此,这并不会自动在包模块的命名空间中包含常量。包中的每个模块仍然必须从mypackage或从中显式导入常量mypackage.constants


19
这应该是公认的答案。如果您正在使用Python 2.5的工作或更高版本,你也可以使用一个明确的相对进口以及描述这里from . import MY_CONSTANT
ThatAintWorking

第二种方法不是只对常量有效吗?from mypackage.constants import *MY_CONSTANT在每个子模块中放置的副本,而不是引用相同的变量
hardmooth

@hardmooth:不完全是。这些值是通过引用复制的,因此,如果您要MY_CONSTANT在任何模块中进行突变,它将在所有地方进行突变。如果您要重新分配MY_CONSTANT任何模块,则只会影响该模块。如果您打算这样做,则必须按属性进行引用,即mypackage.constants.MY_CONSTANT
詹森·库姆斯

7
该示例的一个陷阱是,如果mymodule.py在此__init__.py之前导入MY_CONSTANT = 42,将失败,因为mymodule.py MY_CONSTANT尚未定义何时导入。因此,需要移至MY_CONSTANT = 42上方import mymodule
markmnl

变量如何?它询问的是变量,而不是常量。python如何处理包内的变量?如果包内的变量已更改怎么办?
TomSawyer

31

你不能这样做。您必须将常量明确地导入每个模块的命名空间中。实现此目的的最佳方法是在“ config”模块中定义常量,并将其导入所需的任何位置:

# mypackage/config.py
MY_CONST = 17

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

是的,我想要一个配置文件。我只是认为init .py是一个好地方。您的解决方案听起来像是标准做法。是吗?
Andrei Vajna II

1
好点子。我没有意识到问题是将常量自动放置在所有包模块的名称空间中。
詹森·库姆斯

但是每次脚本导入config.py时,都会执行其中的代码。如果config.py中的代码仅运行一次,您会如何建议?假设我正在读取config.py中的settings.json文件,并且我不想每次导入config.py时都将open()打开。
Augiwan 2014年

@UGS这不是Python的工作方式。每个模块仅执行一次。第二次导入时,模块已在中缓存sys.modules
Ferdinand Beyer 2014年

@FerdinandBeyer糟糕!我忘了提到我是从几个脚本而不是同一脚本中导入config.py的。假设a.py正在导入config.py和b.py,而b.py正在导入config.py。我想知道是否有可能确保config.py中的代码仅执行一次。
Augiwan 2014年

2

您可以在任何地方定义全局变量,但这是一个非常糟糕的主意。导入__builtin__模块并修改或向该模块添加属性,突然间您有了新的内置常量或函数。实际上,当我的应用程序安装gettext时,我在所有模块中都获得了_()函数,而无需导入任何内容。因此这是可能的,但当然仅适用于应用程序类型的项目,而不适用于可重用的包或模块。

而且我想没人会推荐这种做法。命名空间有什么问题?说应用程序版本模块,这样我可以有像“全局”变量version.VERSIONversion.PACKAGE_NAME等等。


0

只是想补充一点,可以使用config.ini文件使用常量,并使用configparser库在脚本中对其进行解析。这样,您可以在多种情况下使用常量。例如,如果您有两个单独的url请求的参数常量,只需将它们标记为:

mymodule/config.ini
[request0]
conn = 'admin@localhost'
pass = 'admin'
...

[request1]
conn = 'barney@localhost'
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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.