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]