在被导入模块的全局变量的可见性在被导入模块的全局变量的可见性(Visibility of globa

2019-05-08 14:55发布

我碰到了一下墙上的一个Python脚本导入模块。 我会尽我所能来描述错误,为什么我碰到它,为什么我绑这种特殊的方式来解决我的问题(我将在第二描述):

让我们假设我有我已经定义了一些实用功能/ classes,它指的是在其中该辅助模块将被导入的命名空间中定义的实体模块(让“一”是这样的实体):

模块1:

def f():
    print a

然后我有主程序,其中“a”的定义,到了我想要导入这些实用程序:

import module1
a=3
module1.f()

执行程序将触发以下错误:

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

类似的问题已经被问在过去(前两天,德呃)和几个解决方案已经提出,但是我真的不认为这符合我的要求。 这里是我的特殊背景下:

我试图让它连接到MySQL数据库服务器和显示/修改数据与GUI Python程序。 对于洁净度的缘故,我定义的辅助/效用MySQL相关的功能的一群在一个单独的文件。 然而,它们都有一个共同的变量,这是我原先公用事业模块定义,并且其是从MySQLdb的模块的光标对象。 我后来认识到光标对象(其用于与分贝服务器通信)应在主模块中进行定义, 这样既被导入到它的主模块和任何可以访问该对象。

最终的结果会是这样的:

utilities_module.py:

def utility_1(args):
    code which references a variable named "cur"
def utility_n(args):
    etcetera

而我的主要模块:

program.py:

import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor()  #cur is defined!
from utilities_module import *

然后,当我尝试调用任何实用程序功能,它触发错误前面提到的“没有定义的全局名称”。

一个特别的建议是有一个“从程序导入CUR”语句的程序文件,像这样的:

utilities_module.py:

from program import cur
#rest of function definitions

program.py:

import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor()  #cur is defined!
from utilities_module import *

但是,这是循环导入或类似的东西,并底线,它崩溃了。 所以我的问题是:

我在地狱里怎样才能让“小人”的对象,主要的模块中定义的,要被导入到它的辅助功能可见?

您的时间,并感谢我最深的歉意,如果该解决方案已在别处发表。 我只是找不到自己的答案,我有我的书没有更多的花样。

Answer 1:

在Python全局是全局的一个模块 ,而不是在所有的模块。 (很多人都被这个困惑,因为,说,C,全球在所有执行文件,除非你明确地使它同static )。

有不同的方法来解决这个问题,根据您的实际使用情况。


甚至走这条路之前,问问自己这是否真的需要是全球性的。 也许你真的想要一个类,它有f作为一个实例方法,而不仅仅是一个免费的功能? 然后,你可以这样做:

import module1
thingy1 = module1.Thingy(a=3)
thingy1.f()

如果你真的想要一个全球性的,但它只是没有被使用module1 ,在该模块中设置。

import module1
module1.a=3
module1.f()

在另一方面,如果a被一大堆模块的共享,把它放在别的地方,并让每个人都导入它:

import shared_stuff
import module1
shared_stuff.a = 3
module1.f()

...并在module1.py:

import shared_stuff
def f():
    print shared_stuff.a

不要使用from除非该变量的目的是恒定的导入。 from shared_stuff import a将创建一个新的a变量初始化为任何shared_stuff.a在进口时称,这一新a变量不会被分配受到影响shared_stuff.a


或者,你真的需要它是真正的全球性无处不在,就像一个内置的,将其添加到内置模块极少数情况下。 具体细节的Python 2.x和3.x的有所不同 在3.x中,它的工作原理是这样的:

import builtins
import module1
builtins.a = 3
module1.f()


Answer 2:

作为一种变通方法,你可以考虑在外层设置环境变量,就像这样。

main.py:

import os
os.environ['MYVAL'] = str(myintvariable)

mymodule.py:

import os
print os.environ['MYVAL']

作为一个额外的预防措施,处理在模块内没有定义MYVAL的情况。



Answer 3:

函数使用它定义模块的全局变量,而是设定a = 3 ,例如,您应该设置module1.a = 3 。 所以,如果你想cur可作为一个全球性的utilities_module ,设置utilities_module.cur

一个更好的解决办法:不要使用全局变量。 通过您需要的变量到需要它的功能,或者创建一个类来捆绑在一起,所有的数据,并初始化实例时通过。



Answer 4:

这篇文章仅仅是Python的行为的观察我遇到过。 也许你读过的建议没有为你工作,如果你让我在下面做同样的事情。

即,我有包含全局/共享变量(如上面所建议的)的模块:

#sharedstuff.py

globaltimes_randomnode=[]
globalist_randomnode=[]

然后,我有其中进口共享的东西与主要模块:

import sharedstuff as shared

和实际填充这些阵列一些其他模块。 这是由主模块调用。 当退出这些其他模块I可以清楚地看到,该阵列填充。 但主要的模块在阅读他们回来的时候,他们是空的。 这是很奇怪的,我(好,我是新来的Python)。 但是,当我改变我的方式导入主模块在sharedstuff.py:

from globals import *

它的工作(被填充的阵列)。

只是在说'



Answer 5:

这一特定问题最简单的办法将是该会存储光标在全球变化到模块的模块中添加其他功能。 然后,所有其他的功能可以使用它。

模块1:

cursor = None

def setCursor(cur):
    global cursor
    cursor = cur

def method(some, args):
    global cursor
    do_stuff(cursor, some, args)

主程序:

import module1

cursor = get_a_cursor()
module1.setCursor(cursor)
module1.method()


Answer 6:

由于全局的模块具体,你可以添加以下功能,所有导入的模块,然后用它来:

  • 加入单一变量(以字典格式)作为全局那些
  • 将您的模块全局吧。

addglobals =拉姆达X:全局()更新(x)的。

然后,所有你需要传递当前全局是:

导入模块

module.addglobals(全局())



Answer 7:

因为我没有答案看到它上面,我想我会加我简单的解决方法,这仅仅是增加一个global_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


Answer 8:

这样做是让你的模块类,而不是一组非绑定方法的面向对象的方式。 然后,你可以使用__init__或setter方法来从呼叫者在模块方法中设置的变量。



文章来源: Visibility of global variables in imported modules