在 Jupyter notebook 的另一个目录中导入 py 文件

Import py file in another directory in Jupyter notebook

我的问题与 this 有关。我在 Jupyter Notebook 中使用 Python 3.6。我的项目目录是/user/project。在这个目录中,我构建了许多模型,每个模型都有自己的文件夹。但是,有一个通用 functions.py 文件,其中包含我想在所有模型中使用的函数。所以我想将 functions.py 文件保留在 /user/project 中,但能够从 /user/project/model1/user/project/model2 等中的 .ipynb 文件中调用它...如何我可以这样做吗?

没有简单的方法可以将 python 文件导入另一个目录。 这与 jupyter 笔记本无关

这里有 3 个解决你的问题的方法

  1. 您可以将包含要导入的文件的目录添加到您的路径中,然后像这样导入文件:
import sys  
sys.path.insert(0, '/path/to/application/app/folder')

import file
  1. 您可以通过在要导入的文件夹中创建一个空 __init__.py 文件来创建本地模块。关于文件夹层次结构,您必须考虑一些 weird rules

  2. 您可以为要导入的文件创建一个模块并全局安装它。

我建议将 functions.py 作为一个包安装在您的虚拟环境中。这样做有一些好处:

  1. 您可以从位于任何地方但在给定环境(内核)中的任何 iPython 笔记本访问 functions.py 文件。
  2. 一旦您更改了 functions.py 文件中的任何功能,您无需一次又一次地重新加载您的 iPython 笔记本。它会自动重新加载每个更改。

这是完成方法:

  • 在您的项目文件夹中创建 setup.py 文件 (https://docs.python.org/2/distutils/setupscript.html)
  • 激活您的虚拟环境,转到您的项目位置,然后使用此命令pip install -e .
  • 然后,在您的 iPython 笔记本中:

    %load_ext 自动重载

    %自动重载 1

    %aimport yourproject.functions

    从函数导入 *

就是这样!

假设您有一个名为 Jupyter 的文件夹,并且您希望从另一个名为 nn_webserver 的文件夹中导入模块(员工) .

可视化它:

这样做:

import sys
import os

module_path = os.path.abspath(os.path.join('..'))
if module_path not in sys.path:
    sys.path.append(module_path+"\nn_webserver")

from employee import motivation_to_work

查看来自@metakermit

的更多信息

我过去解决了这个问题,方法是在 Jupyter notebook 所在的目录中创建一个符号 link 到它要加载的库,这样 python 就好像模块在正确的路径中一样 。因此,对于上面的示例,您将 运行 以下命令 每个目录 Jupyter 单元格中执行一次:

!ln -s /user/project/functions.py functions.py

然后你可以用

导入
import functions

注意:我只在 Linux 和 Mac Os 上试过这个,所以我不能保证 Windows。

除了 adhg 的回答之外,我建议使用 Pathlib,以实现 Linux/Windows/WSL 路径格式之间的兼容性:

假设文件夹结构如下:

.
├── work
|   ├── notebook.ipynb
|   └── my_python_file.py
├── py
|   ├──modules
|   |    ├──__init__.py # empty
|   |    └──preparations.py
|   ├──__init__.py # empty
|   └── tools.py
├──.git
└── README.md

要在 my_python_file.py(或笔记本 notebook.ipynb)中加载 tools.pypreparations.py

import sys
from pathlib import Path

# in jupyter (lab / notebook), based on notebook path
module_path = str(Path.cwd().parents[0] / "py")
# in standard python
module_path = str(Path.cwd(__file__).parents[0] / "py")

if module_path not in sys.path:
    sys.path.append(module_path)

from modules import preparations
import tools
...

发现自己和 OP 的情况完全一样,打算创建几个笔记本,因此希望将它们组织在不同的子文件夹中

试过这个似乎可以满足我的需要,而且对我来说似乎更干净

import os
os.chdir(os.path.dirname(os.path.dirname(os.getcwd())))

我的功能在上面两层,所以嵌套了两层os.path.dirname(不同的文件夹结构只能是一层或多层)

刚刚实现它并且工作正常,顺便说一句,我正在使用 JupyterLab started...函数所在的两个级别

我一直在思考这个问题,因为我不喜欢 sys.path.append() 的答案。我提出的解决方案是使用内置的 Jupyter 魔术命令来更改当前工作目录。假设你有这个文件结构:

project
├── model1
|   └── notebook1.ipynb
├── model2
|   └── notebook2.ipynb
└── functions.py

无论您是想从 notebook1.ipynb 还是 notebook2.ipynb 导入 functions,您只需在包含您的包导入的单元格之前添加一个包含以下行的单元格:

%cd ..

这会将当前工作目录更改为笔记本的父目录,然后将功能模块的路径添加到 Python 将检查包的默认位置。导入 functions:

import functions

如果您在要导入的同一包目录中有多个模块,这将以类似的方式工作:

project
├── model1
|   └── notebook1.ipynb
├── model2
|   └── notebook2.ipynb
└── package
    ├── functions1.py
    └── functions2.py 

您可以像这样从 package 导入模块 functions1functions2

from package import functions1, functions2

编辑:如下所述,如果包含魔术命令的单元格多次 运行,本地导入将不再有效(当前工作目录将在每次重新更改为上面的目录运行 命令)。为了防止这种情况发生,%cd .. 命令应该在笔记本顶部的自己的单元格中(与导入不在同一个单元格中)并且 导入之前它不会 运行 多次。重新启动内核并 运行 连接所有单元将重置当前工作目录,但仍会 return 所需的 imports/results.