2010-12-03 9 views
70

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

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

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

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

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

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

ValueError: Attempted relative import in non-package

, который выглядит, как это не относится к MyClass как пакеты. Reading the docs:

The __init__.py files are required to make Python treat the directories as containing packages;

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

+6

@ Brent Newey, да, вы правы, относительный импорт, кажется, является постоянной темой, и после прочтения нескольких ответов я все еще чувствовал желание конкретно описать свою ситуацию. После показа этого q на канале #python IRC довольно много людей рекомендуют использовать плоскую структуру каталогов: «Многие люди сопротивляются тому, как Python хочет использовать каталоги и файлы для семантической информации о пространстве имен. Лучше всего просто сдаться и делать чего хочет Питон ». http://jcalderone.livejournal.com/39794.html – eerne 2010-12-03 18:24:45

+8

Может ли кто-нибудь предоставить ссылку на некоторые пакеты реального мира с образцовым макетом каталога или после некоторых соглашений? (в идеале на github) – eerne 2010-12-03 18:31:07

+1

Есть ли `__init __. py` в` test` каталоге? `ValueError: Попытка относительного импорта в non-package` может быть связана с ним. – jfs 2010-12-03 20:48:58

ответ

0

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

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

41

ValueError: Attempted relative import in non-package

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

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

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

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

25

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

папку hierarcy:

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

Смежные вопросы