我有一个类似于下面的目录结构
meta_project
project1
__init__.py
lib
module.py
__init__.py
notebook_folder
notebook.jpynb
当在notebook.jpynb中工作时,如果我尝试使用相对导入来访问module.py中的函数function():
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笔记本中尝试调用另一个目录中的本地模块中的函数有关,该目录具有不同的一般和特定方面。
来这里寻找在notebook中工作时将代码抽象为子模块的最佳实践。我不确定是否有最佳做法。我一直在提议这个。
项目层次结构如下:
├── 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。
考虑到我在100次中有99次使用Project Jupyter Docker图像在Docker中工作,下面的修改是幂等的
In [1]: cd /home/jovyan
In [2]: from lib.postgres import database_connection
来这里寻找在notebook中工作时将代码抽象为子模块的最佳实践。我不确定是否有最佳做法。我一直在提议这个。
项目层次结构如下:
├── 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。
考虑到我在100次中有99次使用Project Jupyter Docker图像在Docker中工作,下面的修改是幂等的
In [1]: cd /home/jovyan
In [2]: from lib.postgres import database_connection
我发现python-dotenv非常有效地解决了这个问题。您的项目结构最终会略有变化,但笔记本中的代码更简单一些,并且在不同笔记本中保持一致。
对于您的项目,做一点安装。
pipenv install python-dotenv
然后,项目变更为:
├── .env (this can be empty)
├── ipynb
│ ├── 20170609-Examine_Database_Requirements.ipynb
│ └── 20170609-Initial_Database_Connection.ipynb
└── lib
├── __init__.py
└── postgres.py
最后,您的导入更改为:
import os
import sys
from dotenv import find_dotenv
sys.path.append(os.path.dirname(find_dotenv()))
这个包的优点是你的笔记本可以有好几个目录。Python-dotenv将在父目录中找到最接近的一个并使用它。这种方法的+2是jupyter将在启动时从.env文件加载环境变量。双重打击。