Структура пакета Python

У меня есть пакет 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

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

Ответы

Ответ 1

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

from myproject import models

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

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

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

python myproject/scripts/myscript.py

к

python -c 'import myproject.scripts.myscript'

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

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

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

Ответ 2

Ваш проект не находится на вашем пути.

Вариант A

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

Вариант B

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

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