Структура пакета Python - PullRequest
16 голосов
/ 21 апреля 2011

У меня есть пакет Python с несколькими подпакетами.

myproject/
  __init__.py
  models/
    __init__.py
    ...
  controllers/
    __init__.py
    ..
  scripts/
    __init__.py
    myscript.py

В myproject.scripts.myscript как я могу получить доступ к myproject.models? Я пробовал

from myproject import models # No module named myproject
import models # No module named models
from .. import models # Attempted relative import in non-package

Я должен был решить это раньше, но я никогда не могу вспомнить, как это должно быть сделано. Это просто не интуитивно для меня.

Ответы [ 2 ]

20 голосов
/ 21 апреля 2011

Это правильная версия:

from myproject import models

Если это не удается с ImportError: No module named foo, это потому, что вы не установили PYTHONPATH для включения каталога, который содержит myproject/.

Боюсь, что другие люди предложат трюки, чтобы вы могли избежать установки PYTHONPATH. Я призываю вас игнорировать их. Вот почему существует PYTHONPATH: чтобы сообщить Python, где искать код для загрузки. Он надежен, достаточно хорошо документирован и переносим во многие среды. Трюки, которые играют люди, чтобы избежать необходимости устанавливать его, не являются чем-то из этого.

Явный относительный импорт будет работать даже без установки PYTHONPATH, поскольку он может просто перемещаться по иерархии каталогов, пока не найдет нужное место, ему не нужно найти вершину и затем спуститься. Однако это не работает в сценарии, который вы передаете в качестве аргумента командной строки python (или, что эквивалентно, вызывается напрямую с помощью строки #!/usr/bin/python). Это связано с тем, что в обоих этих случаях он становится модулем __main__ процесса. От __main__ идти некуда - уже наверху! Если вы вызовете код в своем скрипте путем импорта этого модуля, тогда все будет хорошо. То есть сравните:

python myproject/scripts/myscript.py

до

python -c 'import myproject.scripts.myscript'

Вы можете воспользоваться этим, не выполняя ваш скрипт-модуль напрямую, а создав bin/myscript, который выполняет импорт и, возможно, вызывает основную функцию:

import myprojects.scripts.myscript
myprojects.scripts.myscript.main()

Сравните с тем, как определены сценарии командной строки Twisted: http://twistedmatrix.com/trac/browser/trunk/bin/twistd

2 голосов
/ 21 апреля 2011

Ваш проект не на вашем пути.

Вариант А

  • Установите ваш пакет, чтобы python мог найти его по абсолютному имени из любого места (используя from myproject import models)

Вариант B

  • Хитрость для добавления относительного родителя к вашему пути
  • sys.path.append(os.path.abspath('..'))

Рекомендуется первый вариант.

...