Python 2.7 从自身导入第一个模块的另一个模块访问模块的功能
很抱歉让人困惑的标题,我试图在标题中尽可能多地融入问题Python 2.7 从自身导入第一个模块的另一个模块访问模块的功能,python-2.7,tkinter,importerror,Python 2.7,Tkinter,Importerror,很抱歉让人困惑的标题,我试图在标题中尽可能多地融入问题 情景: 我有一个模块(比如ModuleA),其中包含一些Tkinter GUI元素的类定义。 这些元素还绑定了某些事件/函数(如'',…) 现在还有另一个模块(比如ModuleB)。这是程序的主要(核心)。在这个模块中,我导入ModuleA,以使用其对象。ModuleA的对象在数组中有一个位置(比如Array1),还有另一个数组(比如Array2)它只存储数组1的每个对象的一个数据成员的值,这些数据成员由事件绑定操作 因此,问题在于当发生
情景: 我有一个模块(比如
ModuleA
),其中包含一些Tkinter GUI元素的类定义。
这些元素还绑定了某些事件/函数(如'',…
)
现在还有另一个模块(比如ModuleB
)。这是程序的主要(核心)。在这个模块中,我导入ModuleA
,以使用其对象。ModuleA
的对象在数组中有一个位置(比如Array1
),还有另一个数组(比如Array2
)它只存储数组1
的每个对象的一个数据成员的值,这些数据成员由事件绑定操作
因此,问题在于当发生事件时,模块a
的对象(存储在数组1
中)会根据需要进行可视响应,但在后端,它们相应的数据成员值也必须在数组2中相应地更新
简言之:
我尝试的是:
在ModuleA
对象的事件绑定中,我添加了所需的函数(比如foo
),该函数将处理所需的数组操作,并在ModuleB
中定义,因为它必须处理ModuleB
的Array2
。
但这给了我一个错误没有定义全局名称“foo”
因此,在ModuleA
的类定义中,我添加了global foo
,这也没有解决它
最后,我尝试插入模块a
from ModuleB import foo
它引发了一个ImportError
说它无法导入foo(我猜这是因为ModuleB
本身正在导入ModuleA
因此循环引用)
解决办法
一种清晰可见的解决方案是将整个模块a
(包含类定义)复制到模块b
。
但这并不总是实用的,也不太符合实际
请帮助。事实上,你做错了,假设你有两个模块
moduleA和moduleB。如果将moduleA导入moduleB,则无法导入
moduleB转换成moduleA如果您试图这样做,您应该会得到导入错误
让我们看看你做得不对
下面的是moduleA.py
import moduleB
print " I am moduleA"
class foo():
pass
这是moduleB.py
from moduleA import foo
print "I am moduleB"
python moduleB.py
现在执行moduleB.py
from moduleA import foo
print "I am moduleB"
python moduleB.py
你会得到恐惧,但如果你这样做,它就不会发生
python moduleA.py
上面的过程是错误的,python将不允许这种类型的导入
简单地说,我们在这里创建导入循环,因为在每次第一次导入时,整个模块的顶级代码都将被执行,当然python不允许这样做
要解决您的问题,只需更改模块层次结构
以下是简单的解决方案:
如果您想要两个模块(模块A和模块B)的内容,只需再创建一个模块
moduleC并在moduleC中导入两个模块(moduleA和moduleB),然后执行必要的操作
请参考已编辑的内容,您正在做同样的事情,Python中的循环导入可能会令人困惑。很容易出错,因此如果可能,通常最好避免它们。但是,它们不是非法的,如果您小心,它们可以正常工作
输入import foo
时,导入过程如下:
首先,Python检查sys.modules
字典,查看模块foo
是否已加载。如果已加载,则只需将预先存在的模块放入当前模块的名称空间中(进程将在此停止)
如果不存在,则检查是否可以找到要加载的foo.py
文件。如果不存在,则引发ImportError
,并停止进程
如果找到文件,将创建一个新的空模块对象,并将其放入名为foo
的sys.modules
下
然后,Python打开文件并开始执行它,使用在步骤3中创建的模块对象作为本地名称空间
现在,如果上面描述的foo
模块有自己的import
语句,那么导入过程可以递归,在继续执行foo
模块的代码之前加载另一个模块。但是,由于空模块对象在再次导入之前被添加到sys.modules
字典中如果文件被处理,它将不会一直循环并多次尝试加载同一个文件(在大多数情况下)
有些事情可能会出错
如果foo
作为脚本执行(而不是由其他模块导入),它是sys中的初始条目。模块
将以\uuuuu main\uuuuu
的名称命名,而不是foo
。这意味着如果从其他地方导入foo
,您将得到相同代码的两个副本。这是一个例外,一般规则是一个模块不会被加载两次,这可能会让您措手不及在某些情况下,你需要保护自己
此外,如果循环导入的模块彼此进行顶级访问,如果它们以错误的顺序导入(或任何顺序,如果它们都以错误的方式从顶级引用彼此的内容),您将遇到麻烦。通过确保在模块加载时尽可能少地运行代码,可以避免大多数问题(将其放入函数中!)。然后在加载所有内容后,从定义良好的入口点调用函数
所以,在你的情况下,我要检查以下几点:
您是否需要从moduleB import foo执行操作?您是否可以稍后执行import moduleB
操作并访问moduleB.foo
?这将是最简单的修复方法(尽管它不会修复所有可能的问题)。import ModuleA
def foo():
# do whatever
Array1 = [ModuleA.bar(i) for i in range(10)]
Array2 = [whatever]
import ModuleB # import order is important here!
import ModuleA
if __name__ == "__main__":
# do stuff
import ModuleA
def foo():
#do stuff
def setupArrays():
global Array1, Array2 # lets us create these global variables
Array1 = [ModuleA.bar(i) for i in range(10)]
Array2 = [whatever]
import ModuleA, ModuleB # import order doesn't matter
if __name__ == "__main__":
ModuleB.setupArrays()
# do stuff
# No import statement here! Circular imports avoided!
class bar():
def __init__(self, data, callback):
self.data = data
# bind stuff to call the callback function provided
import ModuleA
def foo():
# do whatever
Array1 = [ModuleA.bar(i, foo) for i in range(10)]
Array2 = [whatever]