кошмар с относительным импортом, как действительно оживляет 366 работ?

У меня есть "каноническая файловая структура" как этот (я даю разумные имена для упрощения чтения):

mainpack/

  __main__.py
  __init__.py 

  - helpers/
     __init__.py
     path.py

  - network/
     __init__.py
     clientlib.py
     server.py

  - gui/
     __init__.py
     mainwindow.py
     controllers.py

В этой структуре например, модули, содержавшиеся в каждом пакете, могут хотеть получить доступ helpers утилиты через относительный импорт в чем-то как:

# network/clientlib.py
from ..helpers.path import create_dir

Программа является runned "как сценарием" использование __main__.py файл таким образом:

python mainpack/

При попытке следовать за PEP 366 я вставил __main__.py эти строки:

___package___ = "mainpack"
from .network.clientlib import helloclient 

Но при выполнении:

$ python mainpack 
Traceback (most recent call last):
  File "/usr/lib/python2.6/runpy.py", line 122, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.6/runpy.py", line 34, in _run_code
    exec code in run_globals
  File "path/mainpack/__main__.py", line 2, in 
    from .network.clientlib import helloclient
SystemError: Parent module 'mainpack' not loaded, cannot perform relative import

Что случилось? Что корректный путь состоит в том, чтобы обработать и эффективно использовать относительный импорт?

Я попытался также добавить текущий каталог к PYTHONPATH, ничто не изменяется.

31
задан CharlesB 25 February 2013 в 15:20
поделиться

1 ответ

Код загрузки кажется чем-то вроде this:

    try:
        return sys.modules[pkgname]
    except KeyError:
        if level < 1:
            warn("Parent module '%s' not found while handling "
                 "absolute import" % pkgname, RuntimeWarning, 1)
            return None
        else:
            raise SystemError, ("Parent module '%s' not loaded, cannot "
                                "perform relative import" % pkgname)

что заставляет меня думать, что, возможно, ваш модуль не находится в sys.path. Если вы запустите Python (нормально) и просто напечатаете "import mainpack" в приглашении, что он сделает? Он должен быть в состоянии найти его.

Я попробовал это сам и получил ту же ошибку. Почитав немного, я нашел следующее решение:

# foo/__main__.py
import sys
mod = __import__('foo')
sys.modules["foo"]=mod

__package__='foo'
from .bar import hello

hello()

Мне оно кажется немного хакерским, но оно работает. Похоже, что хитрость заключается в том, чтобы убедиться, что пакет foo загружен, так что импорт может быть относительным.

7
ответ дан 27 November 2019 в 22:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: