使用Python3从另一个目录中的模块导入本地函数,并在Jupyter笔记本中使用相对导入
我有一个类似于下面的目录结构使用Python3从另一个目录中的模块导入本地函数,并在Jupyter笔记本中使用相对导入,python,jupyter-notebook,relative-import,Python,Jupyter Notebook,Relative Import,我有一个类似于下面的目录结构 meta_project project1 __init__.py lib module.py __init__.py notebook_folder notebook.jpynb 在notebook.jpynb中工作时,如果我尝试使用相对导入来访问module.py中的函数function(),请执行以下操作: from ..project1.lib.
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
SystemError回溯(最近一次调用)
在()
---->1 from..project1.lib.module导入函数
SystemError:未加载父模块“”,无法执行相对导入
有没有什么方法可以使用相对导入来实现这一点
注意,笔记本服务器是在meta_项目
目录级别实例化的,因此它应该可以访问这些文件中的信息
另外,请注意,至少最初打算的project1
没有被视为一个模块,因此没有\uuuu init\uuuuuuuuuu.py
文件,它只是作为一个文件系统目录。如果问题的解决方案需要将其视为一个模块,并包含一个\uuuu init\uuuuu.py
文件(即使是一个空白文件),这很好,但这样做不足以解决问题
我在机器之间共享这个目录,相对导入允许我在任何地方都使用相同的代码&我经常使用笔记本进行快速原型设计,因此涉及将绝对路径拼凑在一起的建议不太可能有帮助
编辑:这不同于,它通常在Python3中讨论相对导入,特别是从包目录中运行脚本。这与在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(...)
请注意,如果您还没有空的\uuuu init\uuuuuy.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
import project_path
import lib
这是因为默认情况下Jupyter笔记本可以解析cd
命令。注意,这并没有利用Python笔记本的魔力。它只需不加前缀%bash
即可工作
考虑到我在Docker工作的100次中有99次使用其中一个,下面的修改是幂等的
In [1]: cd /home/jovyan
In [2]: from lib.postgres import database_connection
到目前为止,被接受的答案对我来说最有效。然而,我一直担心的是,可能会出现这样的情况:我可能会将笔记本
目录重构为子目录,需要更改每个笔记本中的模块路径
。我决定在每个笔记本目录中添加一个python文件来导入所需的模块
因此,具有以下项目结构:
project
|__notebooks
|__explore
|__ notebook1.ipynb
|__ notebook2.ipynb
|__ project_path.py
|__ explain
|__notebook1.ipynb
|__project_path.py
|__lib
|__ __init__.py
|__ module.py
我在每个笔记本子目录(notebooks/explore
和notebooks/explain
)中添加了文件project\u path.py
)。此文件包含相对导入的代码(来自@metakermit):
这样,我只需要在project_path.py
文件中进行相对导入,而不是在笔记本中。在导入lib
之前,笔记本文件只需导入project\u path
。例如,在0.0-notebook.ipynb
中:
In [1]: cd ..
In [2]: from lib.postgres import database_connection
import project_path
import lib
这里需要注意的是,逆转进口是行不通的。这不起作用:
import lib
import project_path
因此,在导入过程中必须小心。我自己研究这个主题,并阅读了我建议使用的答案,因为它提供了用于更改当前工作目录的上下文管理器
然后你就有了
导入路径
如果path.path('../lib').isdir():
使用path.path(“..”):
导入库
尽管如此,您可以省略isdir
语句
在这里,我将添加打印语句,以便于跟踪所发生的事情
导入路径
进口大熊猫
打印(path.path.getcwd())
打印(path.path('../lib').isdir())
如果path.path('../lib').isdir():
使用path.path(“..”):
打印(path.path.getcwd())
导入库
打印('Success!')
打印(path.path.getcwd())
本例中的哪个输出(其中lib位于/home/jovyan/shared/notebooks/by team/data vis/demos/lib
):
由于该解决方案使用了上下文管理器,因此无论您的内核在单元格之前处于何种状态,也不管导入库代码引发何种异常,您都可以返回到以前的工作目录。我刚刚找到了这个漂亮的解决方案:
import sys; sys.path.insert(0, '..') # add parent folder path where lib folder is
import lib.store_load # store_load is a file on my library folder
您只需要该文件的一些函数
from lib.store_load import your_function_name
如果python版本>=3.3,您不需要文件夹中的init.py文件这是我的2美分:
导入系统
映射模块文件所在的路径。在我的情况下,它是桌面
sys.path.append(“/Users/John/Desktop”)
要么导入整个映射模块,要么使用.notation映射类,如mapping.Shipping()
导入映射#mapping.py是我的模块文件的名称
shipit=mapping.shipping()#shipping是我需要在映射模块中使用的类的名称
或者从映射模块导入特定类
从映射导入映射
shipit=shipping()#现在您不必使用.notation我发现这有助于非常有效地解决此问题。您的项目结构最终会发生轻微的变化
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()))