У меня есть приложение с иерархией пакетов.Существует немало модулей, которые ссылаются на другие модули выше в иерархии пакетов.Как показано ниже, я могу использовать относительный импорт для решения этой проблемы.Однако запуск модуля непосредственно для тестирования завершается неудачно с исключением Attempted relative import in non-package
.
Существует ли лучший способ организовать мое приложение или операторы импорта, чтобы модули могли выполняться по отдельности для тестирования и импортироваться из других модулей??
Пример
\spam
\morespam
child.py
base.py
\eggs
user.py
base.py
class Base(object):
def hello(self):
print 'Um, wot?'
child.py
from ..base import Base # references the parent package correctly,
# but fails when this module is executed individually
class Child(Base):
def hello(self):
print 'Hello, world!'
if __name__ == '__main__':
import unittest
# ... unit test code ...
user.py
from spam.morespam.child import Child
print Child().hello()
Существующее решение
Я обнаружил, что могу добавить следующий заголовок, добавленный в начало модуля, который долженссылочные модули выше в иерархии:
if __name__ == '__main__':
import sys, os
sys.path.append(os.path.abspath(os.path.join(sys.path[0], '..')))
Недостатком является то, что мне нужно добавить этот код повсюду, и он не является постоянным: относительный путь '..'
зависит от глубиныпакет в иерархии.
Другие возможные решения ...
- Я мог бы создать файл .pth с корнем своего приложения.К сожалению, это должно быть добавлено в папку site-packages моей установки Python, так что это не очень специфично для приложения.
- Я мог бы временно добавить корень моего приложения в PYTHONPATH и сделатьвсе мои модули ссылаются на пакеты из корня.Это исключает простоту запуска сценария простым вызовом
python.exe whatever.py
, хотя. - Я мог бы написать какой-то модуль, который при импорте будет искать файл маркера в корневой папке моего приложения.Этот универсальный модуль затем может быть установлен в мою локальную установку Python и импортирован каждым модулем в моем приложении, что гарантирует, что корень находится в PYTHONPATH, независимо от того, какой модуль я выполняю.