Python通配符导入与命名导入

4

好的,我的一个项目出现了一些奇怪的行为,我希望有人能告诉我原因。我的文件结构如下:

MainApp.py
res/
  __init__.py
  elements/
    __init__.py
    MainFrame.py

在 MainFrame.py 中,我定义了一个名为 RPMWindow 的类,它继承自 wx.Frame。
在 MainApp.py 中,这样做是有效的:
from res.elements.MainFrame import *

这个则不行:
from res.elements.MainFrame import RPMWindow

我知道通配符导入不会产生问题,但我更想了解为什么命名导入失败而通配符导入成功。
当使用类名时,我得到了以下回溯信息:
Traceback (most recent call last):
  File "C:\myApps\eclipse\plugins\org.python.pydev.debug_1.5.6.2010033101\pysrc\pydevd.py", line 953, in <module>
    debugger.run(setup['file'], None, None)
  File "C:\myApps\eclipse\plugins\org.python.pydev.debug_1.5.6.2010033101\pysrc\pydevd.py", line 780, in run
    execfile(file, globals, locals) #execute the script
  File "C:\Documents and Settings\Daniel\workspace\RPM UI - V2\src\MainApp.py", line 2, in <module>
    from res.elements.MainFrame import RPMWindow
  File "C:\Documents and Settings\Daniel\workspace\RPM UI - V2\src\res\elements\MainFrame.py", line 2, in <module>
    from res.elements.MenuBar import MenuBarBuilder
  File "C:\Documents and Settings\Daniel\workspace\RPM UI - V2\src\res\elements\MenuBar.py", line 2, in <module>
    from MainApp import _, DataCache
  File "C:\Documents and Settings\Daniel\workspace\RPM UI - V2\src\MainApp.py", line 2, in <module>
    from res.elements.MainFrame import RPMWindow
ImportError: cannot import name RPMWindow

当使用通配符导入时,我不会收到回溯信息,并且我的应用程序将打开。

1
你能提供使用命名导入时实际的回溯信息吗? - Will McCutchen
请说明“this doesn't work”是什么意思。在第一个例子中,您是否实际上正在导入 RPMWindow? - joaquin
3个回答

8

您遇到了循环导入的问题:

MainFrame.py 间接导入 MainApp.py,而 MainApp.py 则导入 MainFrame.py。因此,当 MainApp.py 导入 MainFrame.py 时,RPMWindow 类尚未被定义,因此会出现 ImportError。


我已经按照你指出的找到了问题所在,我认为我已经解决了它。谢谢。 - Dan

0

我没有时间去研究为什么通配符对你有效,但是关于你直接名称导入失败的问题,我可以说的是你的代码中存在循环导入:

你试图导入res.elements.MainFrame,但是那部分代码正在尝试导入res.elements.MenuBar,而res.elements.MenuBar又试图再次导入res.elements.MainFrame。换句话说,在你再次尝试导入res.elements.MainFrame之前,你的第一次尝试并没有完成。


0

您的代码存在循环导入:同一模块既被另一个模块所需,也需要使用该模块,这显然是不稳定的。大多数问题可以通过使用import a并稍后引用a.b而不是from a import bfrom a import *来解决。

特别地,永远不要使用from a import *。通配符导入会使您的命名空间混乱,使您的代码难以维护、阅读、理智和可预测。 import afrom a import *之间的区别就像将一个盒子拖进房间和把它的内容倒在地板上的区别。

最好将共享代码移至其自己的模块中,或以某种方式重构出循环导入的需要。循环导入总是表示设计问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接