Python通配符导入Vs命名导入

时间:2010-04-19 17:48:52

标签: python import wildcard named

好吧,我的一个项目中有一些相当奇怪的行为,我希望有人可以告诉我原因。我的文件结构如下所示:

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

使用通配符导入时,我没有收到回溯,我的应用程序也会打开。

3 个答案:

答案 0 :(得分:8)

您有循环导入:

MainFrame.py间接导入MainApp.py,MainApp.py正在导入MainFrame.py。因此,当MainApp.py导入MainFrame.py时,RPMWindow类尚未定义,您将获得ImportError。

答案 1 :(得分:0)

我没有时间研究为什么通配符适合你,但我可以说明你的直接名称导入失败的原因是你的代码中有一个导入周期:

您正尝试导入res.elements.MainFrame,但部分 代码正试图导入res.elements.MenuBar,尝试再次导入res.elements.MainFrame。 IOW,您再次尝试导入res.elements.MainFrame的第一次尝试尚未完成。

答案 2 :(得分:0)

你的代码中有循环导入:同一个模块都是必需的,并且需要使用某个其他模块,当你想到它时,它显然是不稳定的。使用import a并稍后引用a.b代替from a import bfrom a import *可以清除大部分问题。

特别是,从不使用from a import *。通配符导入会破坏您的命名空间,使您的代码不易维护,可读,理智且可预测。 import afrom a import *之间的区别在于将一个盒子拖入一个房间并将其内容全部倒在地板上。

如果您可以将共享代码移动到其自己的模块或以某种方式重构需要进行循环导入,那会更好。循环导入始终表明存在设计问题。