Как выполнить относительный импорт в Python
-
09-10-2019 - |
Вопрос
stuff/
__init__.py
mylib.py
Foo/
__init__.py
main.py
foo/
__init__.py
script.py
script.py
хочет импортировать mylib.py
Это просто пример, но на самом деле я просто хочу сделать относительный импорт модуля в родительском каталоге. Я пробовал разные вещи и получите эту ошибку ...
Attempted relative import beyond toplevel package
Я прочитал где-то, что скрипт откуда начинается программа, не должна в пакете, и я попытался изменить структуру для того, что так ...
stuff/
mylib.py
foo.py // equivalent of main.py in above
foo/
__init__.py
script.py
Но получите ту же ошибку.
Как я могу сделать это? Это даже адекватный подход?
Редактировать: в Python 2
Решение
После возобновления с ним немного больше, я понял, как его настроить, и ради специфичности я не буду использовать имена BAR FO. Мой каталог проекта установлен как ...
tools/
core/
object_editor/
# files that need to use ntlib.py
editor.py # see example at bottom
__init__.py
state_editor/
# files that need to use ntlib.py
__init__.py
ntlib.py
__init__.py # core is the top level package
LICENSE
state_editor.py # equivalent to main.py for the state editor
object_editor.py # equivalent to main.py for the object editor
Линия object_editor.py
выглядит как...
from core.object_editor import editor
Линия editor.py
выглядит как...
from .. import ntlib
или в качестве альтернативы
from core import ntlib
Ключ заключается в том, что в этом примере я дал в вопросе, в рамках в пределах пакета был запущен «главный» скрипт. Как только я переехал, создал определенный пакет (core
) и переместил библиотеку, которую я хотел редакторов поделиться (ntlib
) в этот пакет, все было склонны-дори.
Другие советы
Хотя как длинные «вещи» не в вашем пути Python, у вас нет выбора, чем добавление пути.
Если вы знаете уровень вашего Script.py из вещей, вы можете сделать, например:
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
Я бегаю Python 3.4.2 на Windows 7 и оторваю волосы над этим.
При запуске любого из них:
Python -M Unittest Python -M Unittest Discover
... Я бы получил попытку относительного импорта за пределы ошибки Toplevel Package.
Для меня решение опускало «..» в моем [test_stock.py]. Линия была: от импортных запасов.
Изменил его на: от наличия импортных запасов
.. и это работает.
Структура папки:
C:\
|
+-- stock_alerter
|
+-- __init__.py
+-- stock.py
|
\-- tests
|
+-- __init__.py
\-- test_stock.py
import ..foo..stuff.mylib
должно быть хорошо
Редактировать снял расширение
От Пеп Похоже, что вы не можете использовать относительный импорт для импорта файла, который не упакован.
Так что вам нужно будет добавить __init__.py
надовать и изменить свой импорт на что-то вроде from .mylib import *
Тем не менее, PEP, кажется, не приносит пособие, чтобы MyLib упаковывать в модуле. Таким образом, вам может потребоваться изменить, как вы называете свои функции библиотеки.
Еще одна альтернатива - переместить MyLib в подраздел и импортировать его как from .libpackage import mylib
Если вы на Linux или, возможно, похожего * NIX, вы можете взломать это с SymLinks.
stuff/
mylib.py
foo.py // equivalent of main.py in above
foo/
script.py
mylib.py -> ../mylib.py
foo2/
script2.py
mylib.py -> ../mylib.py
Это, вероятно, не хороший шаблон, чтобы следовать.
В моем случае я выбрал это, потому что у меня были несколько исполняемых файлов, зависящих от одной и той же библиотеки, которая должна была быть введена в отдельные каталоги.
Реализация новых исполняемых испытаний не должна требовать тестового писателя, чтобы оказать глубокое понимание импорта Python.
tests/
common/
commonlib.py
test1/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py
test2/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py