Может ли кто-нибудь объяснить относительный импорт питона?
Я не могу на всю жизнь получить относительный импорт python для работы. Я создал простой пример того, где он не работает:
Структура каталогов:
/__init__.py
/start.py
/parent.py
/sub/__init__.py
/sub/relative.py
/start.py
содержит только: import sub.relative
/sub/relative.py
содержит только from .. import parent
Все остальные файлы пустые.
При выполнении в командной строке следующего:
$ cd /
$ python start.py
Я получаю:
Traceback (most recent call last):
File "start.py", line 1, in <module>
import sub.relative
File "/home/cvondrick/sandbox/sub/relative.py", line 1, in <module>
from .. import parent
ValueError: Attempted relative import beyond toplevel package
Я использую Python 2.6. Почему это так? Как сделать этот пример песочницы?
Ответы
Ответ 1
Вы импортируете из пакета "sub". start.py
не входит в пакет, даже если присутствует __init__.py
.
Вам нужно будет запустить свою программу из одного каталога через parent.py
:
./start.py
./pkg/__init__.py
./pkg/parent.py
./pkg/sub/__init__.py
./pkg/sub/relative.py
С start.py
:
import pkg.sub.relative
Теперь pkg - это пакет верхнего уровня, и ваш относительный импорт должен работать.
Если вы хотите придерживаться своего текущего макета, вы можете просто использовать import parent
. Поскольку вы используете start.py
для запуска вашего интерпретатора, каталог, в котором находится start.py
, находится в вашем пути python. parent.py
живет там как отдельный модуль.
Вы также можете безопасно удалить верхний уровень __init__.py
, если вы ничего не импортируете в script далее в дереве каталогов.
Ответ 2
Если вы собираетесь напрямую позвонить relative.py
и, если вы действительно хотите импортировать из модуля верхнего уровня, вы должны явно добавить его в список sys.path
.
Вот как это должно работать:
# Add this line to the beginning of relative.py file
import sys
sys.path.append('..')
# Now you can do imports from one directory top cause it is in the sys.path
import parent
# And even like this:
from parent import Parent
Если вы считаете, что это может привести к какой-то несогласованности, вы можете использовать это вместо:
sys.path.append(sys.path[0] + "/..")
sys.path[0]
относится к пути, из которого была выполнена точка входа.