упаковка Python для относительного импорта - PullRequest
70 голосов
/ 03 декабря 2010

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

myClass/
    __init__.py
    test/
        demo.py
        benchmark.py
        specs.py
    src/
        __init__.py
        myClass.py

Теперь мои вопросы:

  • Как правильно тестировать файлы из пакета в импортируемом myClass.py?

  • Как бы вы импортировали пакет извне, предполагая, что вы берете myClass в качестве подмодуля в libs / myClass или include / myClass?

До сих пор я не мог найти элегантное решение для этого.Из того, что я понимаю Решение Гвидо , должно быть возможно сделать from ..src import myClass, но это будет ошибка:

ValueError: Attempted relative import in non-package

Что выглядит так, как будто это не относится к myClassкак пакеты. Чтение документов :

Файлы __init__.py необходимы для того, чтобы Python рассматривал каталоги как содержащие пакеты;

Кажется, япропустить что-то, что указывает, где находятся скрипты пакета, я должен использовать .pth?

Ответы [ 3 ]

42 голосов
/ 04 декабря 2010

ValueError: Attempted relative import in non-package

Означает, что вы пытаетесь использовать относительный импорт в модуле, который не является пакетом.Его проблема связана с файлом, который имеет этот оператор from ... import, а не с файлом, который вы пытаетесь импортировать.

Так что, например, если вы выполняете относительный импорт в своих тестах, вы должны сделать свои тестыбыть частью вашего пакета.Это означает

  1. Добавление __init__.py для проверки /
  2. Запуск их из какого-либо внешнего скрипта, например, тестов на носу

Если вы запускаете что-то как python myClass/test/demo.pyОтносительный импорт не будет работать, так как вы используете демонстрационный модуль не как пакет.Относительный импорт требует, чтобы модуль, который их использует, импортировался сам как модуль пакета, from myClass.test.demo import blabla или с относительным импортом.

27 голосов
/ 23 мая 2012

После нескольких часов поисков прошлой ночью я нашел ответ об относительном импорте в python! Или, по крайней мере, простое решение. Лучший способ исправить это - вызвать модули из другого модуля. Скажем, вы хотите demo.py импортировать myClass.py. В папке myClass в корне подпакетов им нужен файл, который вызывает два других. Из того, что я собираю, рабочий каталог всегда считается __main__, поэтому, если вы протестируете импорт из demo.py с помощью скрипта demo.py, вы получите эту ошибку. Для иллюстрации:

Иерархия папок:

myClass/
    main.py #arbitrary name, can be anything
    test/
        __init__.py
        demo.py
    src/
        __init__.py
        myClass.py

myClass.py:

def randomMaths(x):
    a = x * 2
    y = x * a
    return y

demo.py:

from ..src import myClass

def printer():
    print(myClass.randomMaths(42))

main.py:

import test.demo

demo.printer()

Если вы запускаете demo.py в интерпретаторе, вы выдадите ошибку, но выполнение main.py не будет. Это немного запутанно, но это работает: D

0 голосов
/ 03 декабря 2010

Внутрипакетные ссылки описывает, как myClass из test/*. Чтобы импортировать пакет извне, вы должны добавить его путь к переменной среды PYTHONPATH перед запуском приложения-импортера или в список sys.path в коде перед его импортом.

Почему from ..src import myClass терпит неудачу: вероятно, src не является пакетом Python, вы не можете импортировать его оттуда. Вы должны добавить его в путь Python, как описано выше.

...