【问题标题】:Python Wildcard Import Vs Named ImportPython 通配符导入与命名导入
【发布时间】:2010-04-19 17:48:51
【问题描述】:

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

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

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

【问题讨论】:

  • 您能否提供使用命名导入时获得的实际回溯?
  • 请指出“这不起作用”是什么意思。你真的是在第一种情况下导入 RPMWindow 吗?

标签: python import wildcard named


【解决方案1】:

你有循环导入:

MainFrame.py 是间接导入 MainApp.py,而 MainApp.py 是导入 MainFrame.py。结果,当 MainApp.py 导入 MainFrame.py 时,RPMWindow 类尚未定义,您会收到 ImportError。

【讨论】:

  • 我发现了这一点,正如你指出的那样。我想我已经解决了。谢谢。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    您的代码中有循环导入:同一个模块既需要也需要使用某个其他模块,当您这样想时,它显然是不稳定的。大多数问题可以通过使用import a 来解决,稍后参考a.b 而不是from a import bfrom a import *

    特别是,从不使用from a import *。通配符导入会使您的命名空间变得混乱,并使您的代码难以维护、可读、健全和可预测。 import afrom a import * 之间的区别在于将盒子拖入房间并将其内容倒在地板上的区别。

    如果您可以将共享代码移到它自己的模块中,或者以某种方式重构出循环导入的需要,那就更好了。循环导入总是表明存在设计问题。

    【讨论】: