属性错误模块对象没有属性——循环导入引起的?

Attribute error module object has no attribute -- Caused by circular imports?

OTS 模块

from Tkinter import *
import openTableApiGet

#bunch of code blah blah blah

openTableApiGet.main() # call to the method in the OpenTableApiGet module

模块 OpenTableApiGet

import OTS

 class Parser:

#Bunch of code in the class doing stuff


def main(): 
#bunch of code

#The main method the complier says this module 
#doesn't have. Outside of `the Parser class, 
#just hanging out on its  own

为什么会这样?是循环导入的罪魁祸首我宁愿保留它,但如果我必须改变它,我会的。我需要写更多的东西来让 Whosebug 开心,所以我希望你能尽快在生活中找到炸玉米饼!

谢谢大家

您是对的,循环导入会使您显示的代码在某些情况下失败。具体来说,如果外部代码首先导入 OpenTableApiGet 模块,OTS 模块将在尝试调用 OpenTableApiGet.main().

时失败

原因如下。当 Python 加载模块时,它从顶部开始并且 运行 按顺序加载每个语句。对于导入语句,它可能必须暂停该模块的执行才能加载另一个模块。

这是一个例子:

A.py:

print 1
import B
print 3

B.py

print 2

这两个简单的会在你导入的时候按顺序打印数字1-3 A

导入语句并不总是暂停。如果要导入的模块已经加载(或者在循环导入的情况下正在加载)Python将不再加载。它只会引用现有的模块对象并将其放入导入命名空间。

C.py:

print 1
import B
print 3
import B
print 4

当第二个 import 语句为 运行 时,不会打印任何内容,因为 B 模块已经加载(通过第一个 import 语句)。

这是您的模块的简单版本,显示了循环导入的问题:

D.py:

print 1
import E
print 5    # this doesn't get a chance to run, nor the code below
x = 7
print 6

E.py:

print 2
import D
print 3
print D.x    # this causes an exception, since D doesn't have an x attribute yet
print 4

如果您导入 D,您将打印 1-3,然后当 E 中的代码试图访问 D 中的全局变量时出现异常尚未初始化。请注意 5 不会在异常之前打印出来,因为 D 的执行暂停等待 E 完成加载。

有几种方法可以修复代码。

首先是一个错误的修复。如果您首先导入 E 而不是 D ,则不会出现异常(尽管您会得到一些乱序打印的数字)。不过,我不建议将此作为解决方案,因为如果您在以后的代码中更改一些导入,它可能会再次中断并且非常混乱!

通常 "best" 方法是重新组织代码以消除模块之间的循环依赖。要么将一些代码从一个模块移动到另一个模块,要么将其分解到第三个模块中,这两个模块都可以导入。这种方法可能会受到学习使用其他语言编程的程序员的大力提倡,因为循环依赖总是会被打破,但这在 Python.

中并不是一个大问题。

另一种选择是允许保留循环导入,但只是为了避免在模块的顶层做太多事情。通常,您可以将麻烦的代码放入一个函数(由模块外部的代码调用),尽管有循环导入,它仍能正常工作。如果没有任何顶级代码试图访问其他模块的内容,循环导入不是问题,因为在导入完成并且所有模块都已完全加载之前,实际上并没有多少 运行 .

这是一个例子:

F.py:

print 2
import D
print 3
def foo():
    print D.x   # not at top level any more
print 4

main.py

import D, F
F.foo()