Импорт подстановочных знаков Python против именованного импорта - PullRequest
4 голосов
/ 19 апреля 2010

Хорошо, у меня довольно странное поведение в одном из моих проектов, и я надеюсь, что кто-то может сказать мне, почему. Моя файловая структура выглядит так:

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 ]

8 голосов
/ 19 апреля 2010

У вас есть круговой импорт:

MainFrame.py косвенно импортирует MainApp.py, а MainApp.py импортирует MainFrame.py. В результате, когда MainApp.py импортирует MainFrame.py, класс RPMWindow еще не определен, и вы получаете ошибку ImportError.

0 голосов
/ 19 апреля 2010

В вашем коде есть циклический импорт: один и тот же модуль требуется и требует использования другого модуля, который, когда вы думаете об этом таким образом, явно шаток. Большинство проблем можно устранить с помощью import a и позже, ссылаясь на a.b вместо from a import b или from a import *.

В частности, никогда использовать from a import *. Импорт подстановочных знаков загромождает ваше пространство имен и делает ваш код менее понятным, читаемым, разумным и предсказуемым. Разница между import a и from a import * - это разница между перетаскиванием ящика в комнату и выливанием его содержимого по всему полу.

Было бы лучше, если бы вы могли переместить совместно используемый код в его собственный модуль или каким-либо образом реорганизовать необходимость циклического импорта. Круговой импорт всегда указывает на проблему проектирования.

0 голосов
/ 19 апреля 2010

У меня нет времени, чтобы выяснить, почему подстановочный знак работает для вас, но что я могу сказать о вашей ошибке при прямом импорте имен, так это о том, что у вас есть цикл импорта в вашем коде:

вы пытаетесь импортировать res.elements.MainFrame, но часть , которую код пытается импортировать res.elements.MenuBar, пытается снова импортировать res.elements.MainFrame. IOW, ваша первая попытка импорта res.elements.MainFrame еще не завершена, прежде чем вы попробуете снова.

...