我有一个类似于以下的目录结构
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)in () ----> 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通常讨论Python 3中的相对导入,特别是从包目录中运行脚本.这与在jupyter笔记本中工作有关,该笔记本试图在另一个具有不同的一般和特定方面的目录中的本地模块中调用函数.
我在这个笔记本中有几乎和你一样的例子,我想以干燥的方式说明相邻模块功能的用法.
我的解决方案是通过向笔记本添加像这样的代码片段来告诉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 Notebook可以解析cd
命令.请注意,这不会使用Python Notebook魔术.它只是工作没有预谋%bash
.
考虑到我使用Project Jupyter Docker图像之一在Docker中工作了100次中的99次,以下修改是幂等的
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
因此在进口期间必须小心。