Python:如何创build一个跨模块variables?
__debug__
variables部分是方便的,因为它会影响每个模块。 如果我想创build另一个同样的variables,我该怎么做呢?
variables(让我们原创,称之为'foo')并不一定是真正的全局性,因为如果我在一个模块中改变foo,它会在其他模块中更新。 如果我可以在导入其他模块之前设置foo,那么他会看到相同的值。
我不认可这个解决scheme,forms或forms。 但是,如果将一个variables添加到__builtin__
模块中,则可以像其他任何包含__builtin__
模块一样访问该variables,默认情况下这些模块都是__builtin__
。
a.py包含
print foo
b.py包含
import __builtin__ __builtin__.foo = 1 import a
结果是打印了“1”。
编辑: __builtin__
模块是可用的本地符号__builtins__
– 这是两个这些答案之间的差异的原因。 还要注意__builtin__
已经被重命名为python3中的builtins
函数。
如果你需要一个全局的跨模块variables,可能只需简单的全局模块级variables即可。
a.py:
var = 1
b.py:
import a print a.var import c print a.var
c.py:
import a a.var = 2
testing:
$ python b.py # -> 1 2
真实世界的例子: Django的global_settings.py (尽pipe在Django应用程序设置中是通过导入对象 django.conf.settings
来使用的)。
定义一个模块(称之为“globalbaz”),并在其中定义variables。 所有使用这个“pseudoglobal”的模块都应该导入“globalbaz”模块,并使用“globalbaz.var_name”
无论变更的位置如何,这都可以工作,您可以在导入之前或之后更改variables。 导入的模块将使用最新的值。 (我在一个玩具的例子中testing了这个)
为了澄清,globalbaz.py看起来就像这样:
var_name = "my_useful_string"
我相信在很多情况下它是有意义的,并且它简化了编程,使得一些全局模型(紧密耦合)已知的全局variables。 本着这种精神,我想详细介绍一下这些模块需要引用的全局模块的概念。
当只有一个这样的模块时,我把它命名为“g”。 在这里面,我为每一个我打算认为是全局的variables分配默认值。 在每个使用它们的模块中,我不使用“from g import var”,因为这只会导致一个本地variables,它只在导入时从g初始化。 我以g.var的格式和“g”作为参考。 作为一个不断提醒,我正在处理其他模块可能访问的variables。
如果这样一个全局variables的值在一个模块的某个函数中被频繁使用,那么这个函数可以创build一个本地副本:var = g.var。 但是,认识到var的赋值是本地的,并且全局g.var不能在赋值中明确引用g.var的情况下不能被更新。
请注意,您也可以使用模块的不同子集共享多个这样的全局模块,以保持更紧密的控制。 我为我的全局模块使用短名称的原因是为了避免在代码中出现太多混乱的代码。 只有一点点经验,它们只有1或2个字符就足以成为助记符。
当x还没有用g定义时,仍然可以对gx进行赋值,然后不同的模块可以访问gx。然而,即使解释器允许它,这种方法也不是那么透明,而且我避免它。 由于赋值variables名称中的拼写错误,仍然有可能在g中意外创build新variables。 有时候检查dir(g)有助于发现任何可能由这样的事故引起的意外名字。
你可以将一个模块的全局variables传递给另一个模块:
在模块A中:
import module_b my_var=2 module_b.do_something_with_my_globals(globals()) print my_var
在模块B中:
def do_something_with_my_globals(glob): # glob is simply a dict. glob["my_var"]=3
全局variables通常是一个坏主意,但你可以通过赋值__builtins__
:
__builtins__.foo = 'something' print foo
而且,模块本身是可以从任何模块访问的variables。 所以如果你定义一个名为my_globals.py
的模块:
# my_globals.py foo = 'something'
那么你可以在任何地方使用它:
import my_globals print my_globals.foo
使用模块而不是修改__builtins__
通常是做这种全局variables的更简单的方法。
您可以使用模块级别的variables来做到这一点。 无论从哪个模块导入,模块都是一样的。 所以你可以在任何模块中使variables成为一个模块级的variables,把它放入并访问它或者从其他模块中分配它。 最好是调用一个函数来设置variables的值,或者使它成为某个单例对象的属性。 这样,如果最终需要在variables更改时运行一些代码,则可以在不中断模块的外部接口的情况下执行此操作。
通常情况下,做事情并不是一个好方法 – 全局使用很less,但我认为这是最简单的方法。
这听起来像修改__builtin__
名称空间。 去做吧:
import __builtin__ __builtin__.foo = 'some-value'
不要直接使用__builtins__
(注意多余的“s”) – 显然这可以是字典或模块。 感谢ΤΖΩΤΖΙΟΥ指出这一点,更多可以在这里find。
现在foo
可以在任何地方使用。
我不推荐一般这样做,但是这是由程序员决定的。
分配给它必须按照上面的方式完成,只要设置foo = 'some-other-value'
将只在当前命名空间中设置它。
我想发布一个答案,有一个情况下,variables将不会被发现。
周期性import可能会打破模块行为。
例如:
first.py
import second var = 1
second.py
import first print(first.var) # will throw an error because the order of execution happens before var gets declared.
main.py
import first
在这个例子中,它应该是显而易见的,但是在一个庞大的代码库中,这可能会让人感到困惑。
我使用这个几个内置的原始函数,我觉得真的很失踪。 一个例子是一个find函数,它具有与filter,map,reduce相同的用法语义。
def builtin_find(f, x, d=None): for i in x: if f(i): return i return d import __builtin__ __builtin__.find = builtin_find
一旦运行(例如,通过在入口点附近导入),所有模块都可以使用find(),显然它是内置的。
find(lambda i: i < 0, [1, 3, 0, -5, -10]) # Yields -5, the first negative.
注意:当然,你可以用filter和另外一条线来testing零长度,或者减less一条古怪的线条,但是我总觉得这很奇怪。
我可以通过使用字典来实现跨模块可修改(或可变 )variables:
# in myapp.__init__ Timeouts = {} # cross-modules global mutable variables for testing purpose Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60 # in myapp.mod1 from myapp import Timeouts def wait_app_up(project_name, port): # wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS'] # ... # in myapp.test.test_mod1 from myapp import Timeouts def test_wait_app_up_fail(self): timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS'] Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3 with self.assertRaises(hlp.TimeoutException) as cm: wait_app_up(PROJECT_NAME, PROJECT_PORT) self.assertEqual("Timeout while waiting for App to start", str(cm.exception)) Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak
启动test_wait_app_up_fail
,实际的超时时间为3秒。