импорт локальной функции из модуля, размещенного в другом каталоге с относительным импортом в Jupyter notebook с помощью python3
у меня есть структура каталогов, аналогичная следующей
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
есть ли способ заставить это работать, используя относительный импорт?
обратите внимание, что экземпляр сервера notebook создается на уровне , поэтому он должен иметь доступ к информации в этот файл.
Обратите также внимание, что по крайней мере, как первоначально предполагалось project1 не считался модулем и поэтому не имеет __init__.py file, он просто подразумевался как каталог файловой системы. Если для решения проблемы требуется рассматривать ее как модуль и включать __init__.py файл (даже пустой) это нормально, но этого недостаточно, чтобы решить проблему.
Я разделяю этот каталог между машинами и относительный импорт позволяет мне использовать то же самое код везде, и я часто использую ноутбуки для быстрого прототипирования, поэтому предложения, которые включают взлом вместе абсолютных путей, вряд ли будут полезны.
Edit: это не похоже на относительный импорт в Python 3, что говорит об относительно импорта в Python 3 в целом и – в частности – запуск скрипта из каталога пакета. Это связано с работой в ноутбуке jupyter, пытающемся вызвать функцию в локальном модуле в другом каталоге который имеет как различные общие, так и частные аспекты.
3 ответов:
у меня был почти такой же пример, как и у вас в этого ноутбука где я хотел проиллюстрировать использование функции соседнего модуля в сухом виде.
мое решение состояло в том, чтобы сообщить Python об этом дополнительном пути импорта модуля, добавив такой фрагмент в ноутбук:
import os import sys module_path = os.path.abspath(os.path.join('..')) if module_path not in sys.path: sys.path.append(module_path)Это позволяет импортировать нужную функцию из иерархии модулей:
from project1.lib.module import function # use the function normally function(...)обратите внимание, что необходимо добавить пустой
__init__.pyфайлы project1/ и lib/ папки, если у вас их еще нет.
пришел сюда в поисках лучших практик в абстрагировании кода в подмодули при работе в ноутбуках. Я не уверен, что есть лучшая практика. Я уже предлагал это.
иерархия проекта как такового:
├── ipynb │ ├── 20170609-Examine_Database_Requirements.ipynb │ └── 20170609-Initial_Database_Connection.ipynb └── lib ├── __init__.py └── postgres.pyи
20170609-Initial_Database_Connection.ipynb:In [1]: cd .. In [2]: from lib.postgres import database_connectionэто работает, потому что по умолчанию ноутбук Jupyter может анализировать . Обратите внимание, что это не использует Python Notebook magic. Он просто работает без добавления
%bash.учитывая, что 99 раз из 100 я работаю в докере, используя один из Project Jupyter Docker images, следующие изменения и идемпотентных
In [1]: cd /home/jovyan In [2]: from lib.postgres import database_connection
до сих пор принятый ответ работал лучше всего для меня. Однако меня всегда беспокоило, что есть вероятный сценарий, когда я могу рефакторинг
notebooksкаталог в подкаталоги, требующие измененияmodule_pathв каждом ноутбуке. Я решил добавить файл python в каждый каталог ноутбука, чтобы импортировать необходимые модули.таким образом, имея следующую структуру проекта:
project |__notebooks |__explore |__ notebook1.ipynb |__ notebook2.ipynb |__ project_path.py |__ explain |__notebook1.ipynb |__project_path.py |__lib |__ __init__.py |__ module.pyя добавил файл
project_path.pyв каждом подкаталоге ноутбука (notebooks/exploreиnotebooks/explain). Этот файл содержит код для относительного импорта (из @metakermit):import sys import os module_path = os.path.abspath(os.path.join(os.pardir, os.pardir)) if module_path not in sys.path: sys.path.append(module_path)таким образом, мне просто нужно сделать относительно импорта в
project_path.pyфайл, а не в блокнотах. Файлы ноутбуков тогда просто нужно будет импортироватьproject_pathперед импортомlib. Например, в0.0-notebook.ipynb:import project_path import libпредостережение здесь заключается в том, что реверсирование импорта не будет работать. ЭТО НЕ РАБОТАЕТ:
import lib import project_pathтаким образом уход должен быть принято во время импорта.
Comments