Python 导入模块中全局变量的可见性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15959534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Visibility of global variables in imported modules
提问by Nubarke
I've run into a bit of a wall importing modules in a Python script. I'll do my best to describe the error, why I run into it, and why I'm tying this particular approach to solve my problem (which I will describe in a second):
我在 Python 脚本中遇到了一些导入模块的问题。我会尽力描述错误,为什么我会遇到它,以及为什么我要结合这种特殊的方法来解决我的问题(我将在稍后描述):
Let's suppose I have a module in which I've defined some utility functions/classes, which refer to entities defined in the namespace into which this auxiliary module will be imported (let "a" be such an entity):
假设我有一个模块,我在其中定义了一些实用程序函数/类,这些函数/类引用在将要导入此辅助模块的命名空间中定义的实体(让“a”成为这样的实体):
module1:
模块1:
def f():
print a
And then I have the main program, where "a" is defined, into which I want to import those utilities:
然后我有主程序,其中定义了“a”,我想将这些实用程序导入其中:
import module1
a=3
module1.f()
Executing the program will trigger the following error:
执行程序会触发如下错误:
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.f()
File "Z:\Python\module1.py", line 3, in f
print a
NameError: global name 'a' is not defined
Similar questions have been askedin the past (two days ago, d'uh) and several solutions have been suggested, however I don't really think these fit my requirements. Here's my particular context:
过去曾问过类似的问题(两天前,d'uh)并提出了几种解决方案,但我认为这些并不符合我的要求。这是我的特定背景:
I'm trying to make a Python program which connects to a MySQL database server and displays/modifies data with a GUI. For cleanliness sake, I've defined the bunch of auxiliary/utility MySQL-related functions in a separate file. However they all have a common variable, which I had originally defined insidethe utilities module, and which is the cursorobject from MySQLdb module. I later realised that the cursorobject (which is used to communicate with the db server) should be defined in the main module, so that both the main module and anything that is imported into it can access that object.
我正在尝试制作一个连接到 MySQL 数据库服务器并使用 GUI 显示/修改数据的 Python 程序。为简洁起见,我在一个单独的文件中定义了一堆辅助/实用 MySQL 相关函数。然而,它们都有一个公共变量,我最初在实用程序模块中定义了它,它是MySQLdb 模块中的游标对象。后来我意识到应该在主模块中定义游标对象(用于与数据库服务器通信),以便主模块和导入到其中的任何内容都可以访问该对象。
End result would be something like this:
最终结果将是这样的:
utilities_module.py:
实用程序_module.py:
def utility_1(args):
code which references a variable named "cur"
def utility_n(args):
etcetera
And my main module:
我的主要模块:
program.py:
程序.py:
import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
And then, as soon as I try to call any of the utilities functions, it triggers the aforementioned "global name not defined" error.
然后,只要我尝试调用任何实用程序函数,它就会触发上述“未定义全局名称”错误。
A particular suggestion was to have a "from program import cur" statement in the utilities file, such as this:
一个特别的建议是在实用程序文件中有一个“from program import cur”语句,例如:
utilities_module.py:
实用程序_module.py:
from program import cur
#rest of function definitions
program.py:
程序.py:
import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
But that's cyclic import or something like that and, bottom line, it crashes too. So my question is:
但这是循环导入或类似的东西,最重要的是,它也会崩溃。所以我的问题是:
How in hell can I make the "cur" object, defined in the main module, visible to those auxiliary functions which are imported into it?
我怎么能让主模块中定义的“cur”对象对导入其中的辅助函数可见?
Thanks for your time and my deepest apologies if the solution has been posted elsewhere. I just can't find the answer myself and I've got no more tricks in my book.
感谢您抽出宝贵时间,如果解决方案已发布在其他地方,我深表歉意。我自己找不到答案,我的书中也没有更多技巧。
采纳答案by abarnert
Globals in Python are global to a module, not across all modules. (Many people are confused by this, because in, say, C, a global is the same across all implementation files unless you explicitly make it static.)
Python 中的全局变量对一个模块是全局的,而不是跨所有模块。(很多人对此感到困惑,因为在 C 中,除非您明确地 make ,否则所有实现文件中的全局变量都是相同的static。)
There are different ways to solve this, depending on your actual use case.
有不同的方法可以解决这个问题,具体取决于您的实际用例。
Before even going down this path, ask yourself whether this really needs to be global. Maybe you really want a class, with fas an instance method, rather than just a free function? Then you could do something like this:
在走这条路之前,先问问自己这是否真的需要全球化。也许你真的想要一个类,f作为一个实例方法,而不仅仅是一个自由函数?然后你可以做这样的事情:
import module1
thingy1 = module1.Thingy(a=3)
thingy1.f()
If you really do want a global, but it's just there to be used by module1, set it in that module.
如果您确实想要一个全局变量,但它只是由 使用module1,请将其设置在该模块中。
import module1
module1.a=3
module1.f()
On the other hand, if ais shared by a whole lot of modules, put it somewhere else, and have everyone import it:
另一方面,如果a被很多模块共享,把它放在其他地方,让每个人都导入它:
import shared_stuff
import module1
shared_stuff.a = 3
module1.f()
… and, in module1.py:
……而且,在 module1.py 中:
import shared_stuff
def f():
print shared_stuff.a
Don'tuse a fromimport unless the variable is intended to be a constant. from shared_stuff import awould create a new avariable initialized to whatever shared_stuff.areferred to at the time of the import, and this new avariable would not be affected by assignments to shared_stuff.a.
from除非变量旨在成为常量,否则不要使用导入。from shared_stuff import a将创建一个新a变量,初始化为shared_stuff.a导入时引用的任何内容,并且这个新a变量不会受到对shared_stuff.a.
Or, in the rare case that you really do need it to be truly global everywhere, like a builtin, add it to the builtin module. The exact details differ between Python 2.x and 3.x. In 3.x, it works like this:
或者,在极少数情况下,您确实需要它在任何地方都真正具有全局性,例如内置模块,请将其添加到内置模块中。Python 2.x 和 3.x 之间的确切细节有所不同。在 3.x 中,它是这样工作的:
import builtins
import module1
builtins.a = 3
module1.f()
回答by kindall
A function uses the globals of the module it's definedin. Instead of setting a = 3, for example, you should be setting module1.a = 3. So, if you want curavailable as a global in utilities_module, set utilities_module.cur.
函数使用定义它的模块的全局变量。a = 3例如,您应该设置而不是设置module1.a = 3。因此,如果您希望cur作为全局 in 可用utilities_module,请设置utilities_module.cur.
A better solution: don't use globals. Pass the variables you need into the functions that need it, or create a class to bundle all the data together, and pass it when initializing the instance.
更好的解决方案:不要使用全局变量。将你需要的变量传递给需要它的函数,或者创建一个类将所有数据捆绑在一起,在初始化实例时传递。
回答by user3336548
This post is just an observation for Python behaviour I encountered. Maybe the advices you read above don't work for you if you made the same thing I did below.
这篇文章只是对我遇到的 Python 行为的观察。如果你做了我在下面做的同样的事情,也许你上面读到的建议对你不起作用。
Namely, I have a module which contains global/shared variables (as suggested above):
即,我有一个包含全局/共享变量的模块(如上所述):
#sharedstuff.py
globaltimes_randomnode=[]
globalist_randomnode=[]
Then I had the main module which imports the shared stuff with:
然后我有了导入共享内容的主模块:
import sharedstuff as shared
and some other modules that actually populated these arrays. These are called by the main module. When exiting these other modules I can clearly see that the arrays are populated. But when reading them back in the main module, they were empty. This was rather strange for me (well, I am new to Python). However, when I change the way I import the sharedstuff.py in the main module to:
以及其他一些实际填充这些数组的模块。这些由主模块调用。退出这些其他模块时,我可以清楚地看到数组已填充。但是当在主模块中读回它们时,它们是空的。这对我来说很奇怪(好吧,我是 Python 新手)。但是,当我将主模块中的 sharedstuff.py 的导入方式更改为:
from globals import *
it worked (the arrays were populated).
它起作用了(填充了数组)。
Just sayin'
只是在说'
回答by Chris Nasr
The easiest solution to this particular problem would have been to add another function within the module that would have stored the cursor in a variable global to the module. Then all the other functions could use it as well.
解决这个特定问题的最简单的方法是在模块中添加另一个函数,该函数会将光标存储在模块的全局变量中。然后所有其他功能也可以使用它。
module1:
模块1:
cursor = None
def setCursor(cur):
global cursor
cursor = cur
def method(some, args):
global cursor
do_stuff(cursor, some, args)
main program:
主程序:
import module1
cursor = get_a_cursor()
module1.setCursor(cursor)
module1.method()
回答by user2589273
Since globals are module specific, you can add the following function to all imported modules, and then use it to:
由于全局变量是特定于模块的,您可以将以下函数添加到所有导入的模块中,然后将其用于:
- Add singular variables (in dictionary format) as globals for those
- Transfer your mainmodule globals to it .
- 添加奇异变量(以字典格式)作为全局变量
- 将您的主模块全局变量转移到它。
addglobals = lambda x: globals().update(x)
addglobals = lambda x: globals().update(x)
Then all you need to pass on current globals is:
那么你需要传递当前的全局变量是:
import module
module.addglobals(globals())
导入模块
module.addglobals(globals())
回答by Vishal
As a workaround, you could consider setting environment variables in the outer layer, like this.
作为一种解决方法,您可以考虑在外层设置环境变量,如下所示。
main.py:
主要.py:
import os
os.environ['MYVAL'] = str(myintvariable)
mymodule.py:
我的模块.py:
import os
myval = None
if 'MYVAL' in os.environ:
myval = os.environ['MYVAL']
As an extra precaution, handle the case when MYVAL is not defined inside the module.
作为额外的预防措施,处理模块内未定义 MYVAL 的情况。
回答by Toby Petty
Since I haven't seen it in the answers above, I thought I would add my simple workaround, which is just to add a global_dictargument to the function requiring the calling module's globals, and then pass the dict into the function when calling; e.g:
由于我没有在上面的答案中看到它,我想我会添加我的简单解决方法,即只是global_dict在需要调用模块的全局变量的函数中添加一个参数,然后在调用时将 dict 传递给函数;例如:
# external_module
def imported_function(global_dict=None):
print(global_dict["a"])
# calling_module
a = 12
from external_module import imported_function
imported_function(global_dict=globals())
>>> 12
回答by coyot
The OOP way of doing this would be to make your module a class instead of a set of unbound methods. Then you could use __init__or a setter method to set the variables from the caller for use in the module methods.
这样做的 OOP 方法是使您的模块成为一个类而不是一组未绑定的方法。然后,您可以使用__init__或 setter 方法来设置来自调用方的变量以在模块方法中使用。

