Python:如何创建跨模块变量?

时间:2022-06-24 23:14:30

The __debug__ variable is handy in part because it affects every module. If I want to create another variable that works the same way, how would I do it?

__debug__变量很方便,部分原因是它影响到每个模块。如果我想创建另一个以相同方式工作的变量,我该怎么做?

The variable (let's be original and call it 'foo') doesn't have to be truly global, in the sense that if I change foo in one module, it is updated in others. I'd be fine if I could set foo before importing other modules and then they would see the same value for it.

变量(我们称它为foo)不一定是全局的,因为如果我在一个模块中改变foo,它在其他模块中会被更新。如果我可以在导入其他模块之前设置foo,然后它们会看到相同的值。

12 个解决方案

#1


95  

I don't endorse this solution in any way, shape or form. But if you add a variable to the __builtin__ module, it will be accessible as if a global from any other module that includes __builtin__ -- which is all of them, by default.

我不会以任何方式、形状或形式支持这个解决方案。但是,如果您向__builtin__模块添加一个变量,那么它就可以访问,就好像任何其他模块(包括__builtin__)的全局变量一样——默认情况下,所有这些模块都包含在内。

a.py contains

一个。py包含

print foo

b.py contains

b。py包含

import __builtin__
__builtin__.foo = 1
import a

The result is that "1" is printed.

结果是“1”被打印出来。

Edit: The __builtin__ module is available as the local symbol __builtins__ -- that's the reason for the discrepancy between two of these answers. Also note that __builtin__ has been renamed to builtins in python3.

编辑:__builtin__模块可以作为本地符号__builtins__使用——这就是两个答案之间存在差异的原因。还要注意,__builtin__在python3中已经被重命名为builtins。

#2


136  

If you need a global cross-module variable maybe just simple global module-level variable will suffice.

如果您需要一个全局跨模块变量,那么简单的全局模块级变量就足够了。

a.py:

a.py:

var = 1

b.py:

b.py:

import a
print a.var
import c
print a.var

c.py:

c.py:

import a
a.var = 2

Test:

测试:

$ python b.py
# -> 1 2

Real-world example: Django's global_settings.py (though in Django apps settings are used by importing the object django.conf.settings).

现实世界的例子:Django global_settings。py(尽管在Django中,应用程序的设置是通过导入对象Django .con .settings来使用的)。

#3


20  

Define a module ( call it "globalbaz" ) and have the variables defined inside it. All the modules using this "pseudoglobal" should import the "globalbaz" module, and refer to it using "globalbaz.var_name"

定义一个模块(称为“globalbaz”),并在其中定义变量。使用这个“伪全局”的所有模块都应该导入“globalbaz”模块,并使用“globalbaz.var_name”引用它

This works regardless of the place of the change, you can change the variable before or after the import. The imported module will use the latest value. (I tested this in a toy example)

不管更改的位置如何,都可以在导入之前或之后更改变量。导入的模块将使用最新的值。(我在一个玩具例子中测试过)

For clarification, globalbaz.py looks just like this:

澄清,globalbaz。py是这样的:

var_name = "my_useful_string"

#4


20  

I believe that there are plenty of circumstances in which it does make sense and it simplifies programming to have some globals that are known across several (tightly coupled) modules. In this spirit, I would like to elaborate a bit on the idea of having a module of globals which is imported by those modules which need to reference them.

我相信在很多情况下,它确实是有意义的,并且它简化了编程,使之具有一些全局变量,这些全局变量是跨几个(紧密耦合的)模块已知的。本着这种精神,我想详细阐述一下拥有全局变量模块的想法,这些全局变量模块是由需要引用全局变量的模块导入的。

When there is only one such module, I name it "g". In it, I assign default values for every variable I intend to treat as global. In each module that uses any of them, I do not use "from g import var", as this only results in a local variable which is initialized from g only at the time of the import. I make most references in the form g.var, and the "g." serves as a constant reminder that I am dealing with a variable that is potentially accessible to other modules.

当只有一个这样的模块时,我将它命名为“g”。在它中,我为我打算作为全局变量的每个变量分配默认值。在使用其中任何一个模块的每个模块中,我都不使用“from g import var”,因为这只会导致在导入时从g初始化一个局部变量。我在表格g中做了大部分的参考。var和“g.”作为一个常量提醒,提醒我正在处理一个可能被其他模块访问的变量。

If the value of such a global variable is to be used frequently in some function in a module, then that function can make a local copy: var = g.var. However, it is important to realize that assignments to var are local, and global g.var cannot be updated without referencing g.var explicitly in an assignment.

如果这个全局变量的值在模块中的某个函数中频繁使用,则该函数可以创建一个本地副本:var = g.var。然而,重要的是要认识到,对var的赋值是局部的、全局的g。在不引用g的情况下,无法更新var。在赋值中显式的var。

Note that you can also have multiple such globals modules shared by different subsets of your modules to keep things a little more tightly controlled. The reason I use short names for my globals modules is to avoid cluttering up the code too much with occurrences of them. With only a little experience, they become mnemonic enough with only 1 or 2 characters.

请注意,您还可以拥有由模块的不同子集共享的多个这样的全局模块,以使控制更加紧密。我为全局模块使用短名称的原因是为了避免代码中出现太多的短名称。只要有一点点经验,他们就会在只有一两个字符的情况下变得足够容易记忆。

It is still possible to make an assignment to, say, g.x when x was not already defined in g, and a different module can then access g.x. However, even though the interpreter permits it, this approach is not so transparent, and I do avoid it. There is still the possibility of accidentally creating a new variable in g as a result of a typo in the variable name for an assignment. Sometimes an examination of dir(g) is useful to discover any surprise names that may have arisen by such accident.

仍然有可能对g进行赋值。当x在g中还没有定义时,另一个模块可以访问g.x。但是,即使解释器允许,这种方法也不是那么透明,所以我避免使用这种方法。仍然有可能会意外地在g中创建一个新的变量,这是由于一个任务的变量名的输入错误造成的。有时,对dir(g)的检查对于发现由于这种意外而产生的任何意外名称是有用的。

#5


9  

You can pass the globals of one module to onother:

您可以将一个模块的全局变量传递给另一个模块:

In Module A:

在模块:

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var

In Module B:

在B模块:

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3

#6


7  

Global variables are usually a bad idea, but you can do this by assigning to __builtins__:

全局变量通常是一个坏主意,但是你可以通过分配给__builtins__来实现:

__builtins__.foo = 'something'
print foo

Also, modules themselves are variables that you can access from any module. So if you define a module called my_globals.py:

另外,模块本身也是可以从任何模块访问的变量。如果你定义一个叫my_globals.py的模块:

# my_globals.py
foo = 'something'

Then you can use that from anywhere as well:

你也可以在任何地方使用:

import my_globals
print my_globals.foo

Using modules rather than modifying __builtins__ is generally a cleaner way to do globals of this sort.

使用模块而不是修改__builtins__通常是执行此类全局变量的更干净的方式。

#7


5  

You can already do this with module-level variables. Modules are the same no matter what module they're being imported from. So you can make the variable a module-level variable in whatever module it makes sense to put it in, and access it or assign to it from other modules. It would be better to call a function to set the variable's value, or to make it a property of some singleton object. That way if you end up needing to run some code when the variable's changed, you can do so without breaking your module's external interface.

您已经可以对模块级变量进行此操作。模块是相同的,不管它们是从哪个模块导入的。所以你可以让这个变量成为模块级的变量在任何有意义的模块中放入它,并从其他模块访问它或分配给它。最好调用一个函数来设置变量的值,或者让它成为某个单例对象的属性。这样,如果您最终需要在变量更改时运行一些代码,您可以在不破坏模块的外部接口的情况下这样做。

It's not usually a great way to do things — using globals seldom is — but I think this is the cleanest way to do it.

这通常不是一个很好的方法——很少使用全局变量——但是我认为这是最干净的方法。

#8


3  

I wanted to post an answer that there is a case where the variable won't be found.

我想发布一个答案,那就是存在这样一种情况:变量不会被找到。

Cyclical imports may break the module behavior.

周期性导入可能会破坏模块行为。

For example:

例如:

first.py

first.py

import second
var = 1

second.py

second.py

import first
print(first.var)  # will throw an error because the order of execution happens before var gets declared.

main.py

main.py

import first

On this is example it should be obvious, but in a large code-base, this can be really confusing.

这是一个很明显的例子,但是在一个大型的代码库中,这可能会让人很困惑。

#9


2  

This sounds like modifying the __builtin__ name space. To do it:

这听起来像是修改__builtin__名称空间。这样做:

import __builtin__
__builtin__.foo = 'some-value'

Do not use the __builtins__ directly (notice the extra "s") - apparently this can be a dictionary or a module. Thanks to ΤΖΩΤΖΙΟΥ for pointing this out, more can be found here.

不要直接使用__builtins__(注意额外的“s”)——显然这可以是字典或模块。感谢ΤΖΩΤΖΙΟΥ指出这一点,更可以在这里找到。

Now foo is available for use everywhere.

现在,foo可以在任何地方使用。

I don't recommend doing this generally, but the use of this is up to the programmer.

我一般不建议这样做,但是使用这个取决于程序员。

Assigning to it must be done as above, just setting foo = 'some-other-value' will only set it in the current namespace.

必须如上所述对其进行赋值,只需设置foo = 'some- others -value'将只在当前名称空间中设置它。

#10


1  

I use this for a couple built-in primitive functions that I felt were really missing. One example is a find function that has the same usage semantics as filter, map, reduce.

我将它用于两个内置的基本函数,我觉得它们确实是缺失的。一个例子是一个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

Once this is run (for instance, by importing near your entry point) all your modules can use find() as though, obviously, it was built in.

运行之后(例如,通过在入口点附近导入),所有模块都可以使用find(),显然,它是内置的。

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

Note: You can do this, of course, with filter and another line to test for zero length, or with reduce in one sort of weird line, but I always felt it was weird.

注意:当然,你可以用过滤器和另一条线来测试零长度,或者用一种奇怪的线来减少,但我总觉得这很奇怪。

#11


0  

I could achieve cross-module modifiable (or mutable) variables by using a dictionary:

我可以通过使用字典实现跨模块可修改(或可变)变量:

# 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

When launching test_wait_app_up_fail, the actual timeout duration is 3 seconds.

当启动test_wait_app_up_fail时,实际超时时间为3秒。

#12


0  

I wondered if it would be possible to avoid some of the disadvantages of using global variables (see e.g. http://wiki.c2.com/?GlobalVariablesAreBad) by using a class namespace rather than a global/module namespace to pass values of variables. The following code indicates that the two methods are essentially identical. There is a slight advantage in using class namespaces as explained below.

我想知道是否可以通过使用类名称空间而不是全局/模块名称空间来传递变量的值来避免使用全局变量(参见http://wiki.c2.com/?GlobalVariablesAreBad)的一些缺点。下面的代码表明这两种方法本质上是相同的。使用类名称空间有一个小优势,如下所示。

The following code fragments also show that attributes or variables may be dynamically created and deleted in both global/module namespaces and class namespaces.

下面的代码片段还显示,可以在全局/模块名称空间和类名称空间中动态创建和删除属性或变量。

wall.py

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

I call this module 'wall' since it is used to bounce variables off of. It will act as a space to temporarily define global variables and class-wide attributes of the empty class 'router'.

我称这个模块为“wall”,因为它是用来将变量从。它将充当临时定义空类“router”的全局变量和类范围属性的空间。

source.py

source.py

import wall
def sourcefn():
    msg = 'Hello world!'
    wall.msg = msg
    wall.router.msg = msg

This module imports wall and defines a single function sourcefn which defines a message and emits it by two different mechanisms, one via globals and one via the router function. Note that the variables wall.msg and wall.router.message are defined here for the first time in their respective namespaces.

该模块导入wall并定义一个函数sourcefn,该函数定义一个消息并通过两个不同的机制(一个通过全局变量,另一个通过路由器函数)发出消息。注意变量墙。味精和wall.router。消息在这里首次在它们各自的名称空间中定义。

dest.py

dest.py

import wall
def destfn():

    if hasattr(wall, 'msg'):
        print 'global: ' + wall.msg
        del wall.msg
    else:
        print 'global: ' + 'no message'

    if hasattr(wall.router, 'msg'):
        print 'router: ' + wall.router.msg
        del wall.router.msg
    else:
        print 'router: ' + 'no message'

This module defines a function destfn which uses the two different mechanisms to receive the messages emitted by source. It allows for the possibility that the variable 'msg' may not exist. destfn also deletes the variables once they have been displayed.

这个模块定义了一个函数destfn,它使用两个不同的机制来接收源发出的消息。它允许变量“msg”可能不存在。destfn还会在变量显示之后删除它们。

main.py

main.py

import source, dest

source.sourcefn()

dest.destfn() # variables deleted after this call
dest.destfn()

This module calls the previously defined functions in sequence. After the first call to dest.destfn the variables wall.msg and wall.router.msg no longer exist.

这个模块按顺序调用前面定义的函数。在第一次调用destination .destfn后,变量壁。味精和wall.router。味精不再存在。

The output from the program is:

程序输出为:

global: Hello world!
router: Hello world!
global: no message
router: no message

世界全球:你好!路由器:你好!全局:没有消息路由器:没有消息

The above code fragments show that the module/global and the class/class variable mechanisms are essentially identical.

上面的代码片段表明,模块/全局和类/类变量机制本质上是相同的。

If a lot of variables are to be shared, namespace pollution can be managed either by using several wall-type modules, e.g. wall1, wall2 etc. or by defining several router-type classes in a single file. The latter is slightly tidier, so perhaps represents a marginal advantage for use of the class-variable mechanism.

如果要共享许多变量,可以通过使用多个wall-type模块(例如wall1、wall2等)或在一个文件中定义多个路由类型类来管理名称空间污染。后者稍微整洁一些,因此对于使用类变量机制来说,可能代表了一个边际优势。

#1


95  

I don't endorse this solution in any way, shape or form. But if you add a variable to the __builtin__ module, it will be accessible as if a global from any other module that includes __builtin__ -- which is all of them, by default.

我不会以任何方式、形状或形式支持这个解决方案。但是,如果您向__builtin__模块添加一个变量,那么它就可以访问,就好像任何其他模块(包括__builtin__)的全局变量一样——默认情况下,所有这些模块都包含在内。

a.py contains

一个。py包含

print foo

b.py contains

b。py包含

import __builtin__
__builtin__.foo = 1
import a

The result is that "1" is printed.

结果是“1”被打印出来。

Edit: The __builtin__ module is available as the local symbol __builtins__ -- that's the reason for the discrepancy between two of these answers. Also note that __builtin__ has been renamed to builtins in python3.

编辑:__builtin__模块可以作为本地符号__builtins__使用——这就是两个答案之间存在差异的原因。还要注意,__builtin__在python3中已经被重命名为builtins。

#2


136  

If you need a global cross-module variable maybe just simple global module-level variable will suffice.

如果您需要一个全局跨模块变量,那么简单的全局模块级变量就足够了。

a.py:

a.py:

var = 1

b.py:

b.py:

import a
print a.var
import c
print a.var

c.py:

c.py:

import a
a.var = 2

Test:

测试:

$ python b.py
# -> 1 2

Real-world example: Django's global_settings.py (though in Django apps settings are used by importing the object django.conf.settings).

现实世界的例子:Django global_settings。py(尽管在Django中,应用程序的设置是通过导入对象Django .con .settings来使用的)。

#3


20  

Define a module ( call it "globalbaz" ) and have the variables defined inside it. All the modules using this "pseudoglobal" should import the "globalbaz" module, and refer to it using "globalbaz.var_name"

定义一个模块(称为“globalbaz”),并在其中定义变量。使用这个“伪全局”的所有模块都应该导入“globalbaz”模块,并使用“globalbaz.var_name”引用它

This works regardless of the place of the change, you can change the variable before or after the import. The imported module will use the latest value. (I tested this in a toy example)

不管更改的位置如何,都可以在导入之前或之后更改变量。导入的模块将使用最新的值。(我在一个玩具例子中测试过)

For clarification, globalbaz.py looks just like this:

澄清,globalbaz。py是这样的:

var_name = "my_useful_string"

#4


20  

I believe that there are plenty of circumstances in which it does make sense and it simplifies programming to have some globals that are known across several (tightly coupled) modules. In this spirit, I would like to elaborate a bit on the idea of having a module of globals which is imported by those modules which need to reference them.

我相信在很多情况下,它确实是有意义的,并且它简化了编程,使之具有一些全局变量,这些全局变量是跨几个(紧密耦合的)模块已知的。本着这种精神,我想详细阐述一下拥有全局变量模块的想法,这些全局变量模块是由需要引用全局变量的模块导入的。

When there is only one such module, I name it "g". In it, I assign default values for every variable I intend to treat as global. In each module that uses any of them, I do not use "from g import var", as this only results in a local variable which is initialized from g only at the time of the import. I make most references in the form g.var, and the "g." serves as a constant reminder that I am dealing with a variable that is potentially accessible to other modules.

当只有一个这样的模块时,我将它命名为“g”。在它中,我为我打算作为全局变量的每个变量分配默认值。在使用其中任何一个模块的每个模块中,我都不使用“from g import var”,因为这只会导致在导入时从g初始化一个局部变量。我在表格g中做了大部分的参考。var和“g.”作为一个常量提醒,提醒我正在处理一个可能被其他模块访问的变量。

If the value of such a global variable is to be used frequently in some function in a module, then that function can make a local copy: var = g.var. However, it is important to realize that assignments to var are local, and global g.var cannot be updated without referencing g.var explicitly in an assignment.

如果这个全局变量的值在模块中的某个函数中频繁使用,则该函数可以创建一个本地副本:var = g.var。然而,重要的是要认识到,对var的赋值是局部的、全局的g。在不引用g的情况下,无法更新var。在赋值中显式的var。

Note that you can also have multiple such globals modules shared by different subsets of your modules to keep things a little more tightly controlled. The reason I use short names for my globals modules is to avoid cluttering up the code too much with occurrences of them. With only a little experience, they become mnemonic enough with only 1 or 2 characters.

请注意,您还可以拥有由模块的不同子集共享的多个这样的全局模块,以使控制更加紧密。我为全局模块使用短名称的原因是为了避免代码中出现太多的短名称。只要有一点点经验,他们就会在只有一两个字符的情况下变得足够容易记忆。

It is still possible to make an assignment to, say, g.x when x was not already defined in g, and a different module can then access g.x. However, even though the interpreter permits it, this approach is not so transparent, and I do avoid it. There is still the possibility of accidentally creating a new variable in g as a result of a typo in the variable name for an assignment. Sometimes an examination of dir(g) is useful to discover any surprise names that may have arisen by such accident.

仍然有可能对g进行赋值。当x在g中还没有定义时,另一个模块可以访问g.x。但是,即使解释器允许,这种方法也不是那么透明,所以我避免使用这种方法。仍然有可能会意外地在g中创建一个新的变量,这是由于一个任务的变量名的输入错误造成的。有时,对dir(g)的检查对于发现由于这种意外而产生的任何意外名称是有用的。

#5


9  

You can pass the globals of one module to onother:

您可以将一个模块的全局变量传递给另一个模块:

In Module A:

在模块:

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var

In Module B:

在B模块:

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3

#6


7  

Global variables are usually a bad idea, but you can do this by assigning to __builtins__:

全局变量通常是一个坏主意,但是你可以通过分配给__builtins__来实现:

__builtins__.foo = 'something'
print foo

Also, modules themselves are variables that you can access from any module. So if you define a module called my_globals.py:

另外,模块本身也是可以从任何模块访问的变量。如果你定义一个叫my_globals.py的模块:

# my_globals.py
foo = 'something'

Then you can use that from anywhere as well:

你也可以在任何地方使用:

import my_globals
print my_globals.foo

Using modules rather than modifying __builtins__ is generally a cleaner way to do globals of this sort.

使用模块而不是修改__builtins__通常是执行此类全局变量的更干净的方式。

#7


5  

You can already do this with module-level variables. Modules are the same no matter what module they're being imported from. So you can make the variable a module-level variable in whatever module it makes sense to put it in, and access it or assign to it from other modules. It would be better to call a function to set the variable's value, or to make it a property of some singleton object. That way if you end up needing to run some code when the variable's changed, you can do so without breaking your module's external interface.

您已经可以对模块级变量进行此操作。模块是相同的,不管它们是从哪个模块导入的。所以你可以让这个变量成为模块级的变量在任何有意义的模块中放入它,并从其他模块访问它或分配给它。最好调用一个函数来设置变量的值,或者让它成为某个单例对象的属性。这样,如果您最终需要在变量更改时运行一些代码,您可以在不破坏模块的外部接口的情况下这样做。

It's not usually a great way to do things — using globals seldom is — but I think this is the cleanest way to do it.

这通常不是一个很好的方法——很少使用全局变量——但是我认为这是最干净的方法。

#8


3  

I wanted to post an answer that there is a case where the variable won't be found.

我想发布一个答案,那就是存在这样一种情况:变量不会被找到。

Cyclical imports may break the module behavior.

周期性导入可能会破坏模块行为。

For example:

例如:

first.py

first.py

import second
var = 1

second.py

second.py

import first
print(first.var)  # will throw an error because the order of execution happens before var gets declared.

main.py

main.py

import first

On this is example it should be obvious, but in a large code-base, this can be really confusing.

这是一个很明显的例子,但是在一个大型的代码库中,这可能会让人很困惑。

#9


2  

This sounds like modifying the __builtin__ name space. To do it:

这听起来像是修改__builtin__名称空间。这样做:

import __builtin__
__builtin__.foo = 'some-value'

Do not use the __builtins__ directly (notice the extra "s") - apparently this can be a dictionary or a module. Thanks to ΤΖΩΤΖΙΟΥ for pointing this out, more can be found here.

不要直接使用__builtins__(注意额外的“s”)——显然这可以是字典或模块。感谢ΤΖΩΤΖΙΟΥ指出这一点,更可以在这里找到。

Now foo is available for use everywhere.

现在,foo可以在任何地方使用。

I don't recommend doing this generally, but the use of this is up to the programmer.

我一般不建议这样做,但是使用这个取决于程序员。

Assigning to it must be done as above, just setting foo = 'some-other-value' will only set it in the current namespace.

必须如上所述对其进行赋值,只需设置foo = 'some- others -value'将只在当前名称空间中设置它。

#10


1  

I use this for a couple built-in primitive functions that I felt were really missing. One example is a find function that has the same usage semantics as filter, map, reduce.

我将它用于两个内置的基本函数,我觉得它们确实是缺失的。一个例子是一个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

Once this is run (for instance, by importing near your entry point) all your modules can use find() as though, obviously, it was built in.

运行之后(例如,通过在入口点附近导入),所有模块都可以使用find(),显然,它是内置的。

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

Note: You can do this, of course, with filter and another line to test for zero length, or with reduce in one sort of weird line, but I always felt it was weird.

注意:当然,你可以用过滤器和另一条线来测试零长度,或者用一种奇怪的线来减少,但我总觉得这很奇怪。

#11


0  

I could achieve cross-module modifiable (or mutable) variables by using a dictionary:

我可以通过使用字典实现跨模块可修改(或可变)变量:

# 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

When launching test_wait_app_up_fail, the actual timeout duration is 3 seconds.

当启动test_wait_app_up_fail时,实际超时时间为3秒。

#12


0  

I wondered if it would be possible to avoid some of the disadvantages of using global variables (see e.g. http://wiki.c2.com/?GlobalVariablesAreBad) by using a class namespace rather than a global/module namespace to pass values of variables. The following code indicates that the two methods are essentially identical. There is a slight advantage in using class namespaces as explained below.

我想知道是否可以通过使用类名称空间而不是全局/模块名称空间来传递变量的值来避免使用全局变量(参见http://wiki.c2.com/?GlobalVariablesAreBad)的一些缺点。下面的代码表明这两种方法本质上是相同的。使用类名称空间有一个小优势,如下所示。

The following code fragments also show that attributes or variables may be dynamically created and deleted in both global/module namespaces and class namespaces.

下面的代码片段还显示,可以在全局/模块名称空间和类名称空间中动态创建和删除属性或变量。

wall.py

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

I call this module 'wall' since it is used to bounce variables off of. It will act as a space to temporarily define global variables and class-wide attributes of the empty class 'router'.

我称这个模块为“wall”,因为它是用来将变量从。它将充当临时定义空类“router”的全局变量和类范围属性的空间。

source.py

source.py

import wall
def sourcefn():
    msg = 'Hello world!'
    wall.msg = msg
    wall.router.msg = msg

This module imports wall and defines a single function sourcefn which defines a message and emits it by two different mechanisms, one via globals and one via the router function. Note that the variables wall.msg and wall.router.message are defined here for the first time in their respective namespaces.

该模块导入wall并定义一个函数sourcefn,该函数定义一个消息并通过两个不同的机制(一个通过全局变量,另一个通过路由器函数)发出消息。注意变量墙。味精和wall.router。消息在这里首次在它们各自的名称空间中定义。

dest.py

dest.py

import wall
def destfn():

    if hasattr(wall, 'msg'):
        print 'global: ' + wall.msg
        del wall.msg
    else:
        print 'global: ' + 'no message'

    if hasattr(wall.router, 'msg'):
        print 'router: ' + wall.router.msg
        del wall.router.msg
    else:
        print 'router: ' + 'no message'

This module defines a function destfn which uses the two different mechanisms to receive the messages emitted by source. It allows for the possibility that the variable 'msg' may not exist. destfn also deletes the variables once they have been displayed.

这个模块定义了一个函数destfn,它使用两个不同的机制来接收源发出的消息。它允许变量“msg”可能不存在。destfn还会在变量显示之后删除它们。

main.py

main.py

import source, dest

source.sourcefn()

dest.destfn() # variables deleted after this call
dest.destfn()

This module calls the previously defined functions in sequence. After the first call to dest.destfn the variables wall.msg and wall.router.msg no longer exist.

这个模块按顺序调用前面定义的函数。在第一次调用destination .destfn后,变量壁。味精和wall.router。味精不再存在。

The output from the program is:

程序输出为:

global: Hello world!
router: Hello world!
global: no message
router: no message

世界全球:你好!路由器:你好!全局:没有消息路由器:没有消息

The above code fragments show that the module/global and the class/class variable mechanisms are essentially identical.

上面的代码片段表明,模块/全局和类/类变量机制本质上是相同的。

If a lot of variables are to be shared, namespace pollution can be managed either by using several wall-type modules, e.g. wall1, wall2 etc. or by defining several router-type classes in a single file. The latter is slightly tidier, so perhaps represents a marginal advantage for use of the class-variable mechanism.

如果要共享许多变量,可以通过使用多个wall-type模块(例如wall1、wall2等)或在一个文件中定义多个路由类型类来管理名称空间污染。后者稍微整洁一些,因此对于使用类变量机制来说,可能代表了一个边际优势。