У меня есть структура каталогов, подобная следующей
meta_project
project1
__init__.py
lib
module.py
__init__.py
notebook_folder
notebook.jpynb
При работе в notebook.jpynb
при попытке использовать относительный импорт , чтобы получить доступ к функции function()
в module.py
с:
from ..project1.lib.module import function
Я получаю следующую ошибку:
SystemError Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function
SystemError: Parent module '' not loaded, cannot perform relative import
Есть ли способ заставить это работать, используя относительный импорт?
Обратите внимание, что сервер записной книжки создается на уровне meta_project
каталога, поэтому он должен иметь доступ к информации в этих файлах.
Также обратите внимание, что, по крайней мере, как изначально предполагалось, project1
он не рассматривался как модуль и, следовательно, не имеет __init__.py
файла, он просто предназначен как каталог файловой системы. Если решение проблемы требует рассматривать его как модуль и включать __init__.py
файл (даже пустой), это нормально, но этого недостаточно для решения проблемы.
Я разделяю этот каталог между машинами, и относительный импорт позволяет мне везде использовать один и тот же код, и я часто использую записные книжки для быстрого прототипирования, поэтому предложения, связанные с объединением абсолютных путей, вряд ли будут полезны.
Изменить: это отличается от относительного импорта в Python 3 , в котором говорится об относительном импорте в Python 3 в целом и, в частности, о запуске сценария из каталога пакета. Это связано с работой в записной книжке jupyter, пытающейся вызвать функцию в локальном модуле в другом каталоге, который имеет как разные общие, так и частные аспекты.
__init__
файлы в каталоге вашего пакета?lib
справочнике.Ответы:
У меня был почти такой же пример, как и у вас в этой записной книжке, где я хотел проиллюстрировать использование функции соседнего модуля в СУХОМ стиле.
Мое решение состояло в том, чтобы сообщить Python об этом дополнительном пути импорта модуля, добавив в блокнот такой фрагмент:
Это позволяет вам импортировать желаемую функцию из иерархии модулей:
Обратите внимание, что необходимо добавить пустые
__init__.py
файлы в папки project1 / и lib /, если у вас их еще нет.источник
Пришел сюда в поисках лучших практик абстрагирования кода до подмодулей при работе в Notebooks. Я не уверен, что есть лучшая практика. Я предлагал это.
Иерархия проекта как таковая:
И от
20170609-Initial_Database_Connection.ipynb
:Это работает, потому что по умолчанию Jupyter Notebook может анализировать
cd
команду. Обратите внимание, что это не использует магию Python Notebook. Он просто работает без добавления%bash
.Учитывая , что в 99 раз из 100 , я работаю в Докер с помощью одного из изображений проекта Jupyter Docker , следующая модификация является идемпотентная
источник
chdir
а не добавляю в путь, так как я заинтересован в импорте из основного репо, а также в взаимодействии с некоторыми файлами там.if os.path.isdir('../lib/'): os.chdir('../lib')
:; или, лучше, используйте../lib/db/
с вашим,postgres.py
чтобы случайно не попасть в каталог более высокого уровня, также содержащий другойlib
.cd ..
дважды.Пока что принятый ответ работал у меня лучше всего. Однако меня всегда беспокоило то, что существует вероятный сценарий, при котором я мог бы
notebooks
преобразовать каталог в подкаталоги, что потребовало бы измененияmodule_path
в каждой записной книжке. Я решил добавить файл python в каждый каталог записной книжки, чтобы импортировать необходимые модули.Таким образом, имея следующую структуру проекта:
Я добавил файл
project_path.py
в каждый подкаталог записной книжки (notebooks/explore
иnotebooks/explain
). Этот файл содержит код для относительного импорта (из @metakermit):Таким образом, мне просто нужно выполнять относительный импорт внутри
project_path.py
файла, а не в записных книжках. Файлы записных книжек тогда просто нужно будет импортироватьproject_path
перед импортомlib
. Например в0.0-notebook.ipynb
:Предостережение здесь в том, что отменить импорт не получится. ЭТО НЕ РАБОТАЕТ:
Таким образом, при импорте необходимо соблюдать осторожность.
источник
Я только что нашел это красивое решение:
Вам просто нужны некоторые функции этого файла
Если версия python> = 3.3 вам не нужен файл init.py в папке
источник
if ".." not in sys.path: ... sys.path.insert(0,"..")
Изучив эту тему самостоятельно и прочитав ответы, я рекомендую использовать библиотеку path.py, поскольку она предоставляет диспетчер контекста для изменения текущего рабочего каталога.
Тогда у вас будет что-то вроде
Хотя можно просто опустить
isdir
заявление.Здесь я добавлю операторы печати, чтобы упростить отслеживание происходящего
который выводит в этом примере (где lib находится в
/home/jovyan/shared/notebooks/by-team/data-vis/demos/lib
):Поскольку решение использует диспетчер контекста, вы гарантированно вернетесь в свой предыдущий рабочий каталог, независимо от того, в каком состоянии находилось ядро перед ячейкой, и какие бы исключения не возникли при импорте кода вашей библиотеки.
источник
Вот мои 2 цента:
import sys
сопоставьте путь, по которому расположен файл модуля. В моем случае это был рабочий стол
sys.path.append ( '/ Users / John / Desktop')
Либо импортируйте весь модуль сопоставления, НО тогда вы должны использовать .notation для сопоставления классов, таких как mapping.Shipping ()
import mapping # mapping.py - это имя моего файла модуля
shipit = mapping.Shipment () #Shipment - это имя класса, который мне нужно использовать в модуле сопоставления.
Или импортируйте конкретный класс из модуля сопоставления
из сопоставления импорт карт
shipit = Shipment () # Теперь не нужно использовать .notation
источник
Я обнаружил, что python-dotenv помогает довольно эффективно решить эту проблему. Структура вашего проекта немного изменится, но код в вашей записной книжке станет немного проще и единообразнее для разных ноутбуков.
Для вашего проекта выполните небольшую установку.
Затем проект изменится на:
И, наконец, ваш импорт изменится на:
+1 для этого пакета - ваши записные книжки могут содержать несколько каталогов. python-dotenv найдет ближайший в родительском каталоге и будет использовать его. +2 для этого подхода заключается в том, что jupyter будет загружать переменные среды из файла .env при запуске. Двойной удар.
источник