Как выполнить относительный импорт в python
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
Я где-то читал, что script, с которого запускается программа, не должен быть в пакете, и я попытался изменить структуру для этого так...
stuff/
mylib.py
foo.py // equivalent of main.py in above
foo/
__init__.py
script.py
но получил ту же ошибку.
Как я могу это сделать? Это даже адекватный подход?
Изменить: в Python 2
Ответы
Ответ 1
После того, как я немного поработал с этим, я понял, как его настроить, и для специфики я не буду использовать имена баров foo. Мой каталог проекта настроен как...
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
Ключ в том, что в примере, который я дал в вопросе, изнутри пакета запускался "основной" script. Как только я переместил его, создал определенный пакет (core
) и переместил библиотеку, в которой я хотел, чтобы редакторы делились (ntlib
) в этот пакет, все было hunky-dory.
Ответ 2
хотя так долго "stuff" не находится в вашем Python Python, у вас нет выбора, кроме добавления пути.
Если вы знаете уровень вашего script.py из материала, который вы можете сделать, например:
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
Ответ 3
Я запускаю Python 3.4.2 на Windows 7 и вырываю волосы из-за этого.
При запуске любого из них:
python -m unittest python -m unittest обнаружить
... Я бы получил ошибку "Попытка относительного импорта за пределы пакета пакетов".
Для меня решение было сбросить ".." в моей [test_stock.py].
Линия была: from..stock import Stock
Изменено: из фондового импорта
.. и он работает.
Структура папки:
C:\
|
+-- stock_alerter
|
+-- __init__.py
+-- stock.py
|
\-- tests
|
+-- __init__.py
\-- test_stock.py
Ответ 4
import ..foo..stuff.mylib
должно быть нормально
EDIT снял расширение
Ответ 5
Из PEP кажется, что вы не можете использовать относительный импорт для импорта файла, который не упакован.
Итак, вам нужно добавить __init__.py
для заполнения и изменения ваших импортных значений на что-то вроде from .mylib import *
Тем не менее, PEP, похоже, не учитывает, что mylib упакован в модуль. Поэтому вам может потребоваться изменить способ вызова функций библиотеки.
Другой вариант - переместить mylib в подпакет и импортировать его как from .libpackage import mylib
Ответ 6
Если вы работаете в Linux или, возможно, похожий * nix, вы можете взломать это с помощью символических ссылок.
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