将 py 文件导入 Jupyter 笔记本的另一个目录

我的问题与 这个有关。我在 Jupiter Notebook 中使用 Python 3.6。我的项目目录是 /user/project。在这个目录中,我构建了许多模型,每个模型都有自己的文件夹。但是,有一个通用的 functions.py文件,其中包含我想在所有模型中使用的函数。因此,我想保持在 /user/projectfunctions.py文件,但能够从 /user/project/model1/user/project/model2.ipynb文件调用它。.我怎么能这么做?

178353 次浏览

没有简单的方法导入另一个目录中的 python 文件。 这和木星笔记本无关

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

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


import file
  1. 可以通过在要导入的文件夹中包含一个空的 __init__.py文件来创建本地模块。有一些关于文件夹层次结构的 奇怪的规矩需要考虑。

  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 自动重载

    % autoreload 1

    % aimport your project. function

    从函数导入 *

就是这样!

假设您有一个名为 朱庇特的文件夹,并且希望从另一个名为 Nn _ webserver的文件夹导入模块(雇员)。

想象一下:

enter image description here

这样做:

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

请参阅来自@metkermit 的其他信息 给你

过去,我通过在 朱庇特笔记本所在的目录中创建一个符号链接来解决这个问题,这个链接指向它想要加载的库,这样 python 举止就像模块在正确的路径中一样。因此,对于上面的示例,您可以在 朱庇特单元格中运行以下命令 每个目录一次:

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

然后你就可以用

import functions

注意: 我只在 Linux 和 Mac OS 上试过,所以我不能担保 Windows。

除了 adhg 给出的答案之外,为了兼容 Linux/Windows/WSL 路径格式,我建议使用 Pathlib:

假设文件夹结构如下:

.
├── 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(不同的文件夹结构可能只有一个或多个)

刚刚实现,工作正常,顺便说一下,我正在使用木星实验室开始... 两个级别以上的功能驻留

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

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

编辑: 正如下面指出的,如果包含 magic 命令的单元格运行多次,本地导入将不再工作(每次重新运行命令时,当前工作目录将更改为上面的目录)。为了防止这种情况发生,%cd ..命令应该位于笔记本电脑顶部自己的单元格中(与导入的单元格不在同一个单元格中) ,而 之前则位于导入的单元格中,这样就不会多次运行它。重新启动内核并运行所有单元格将重置当前工作目录,但仍将返回所需的导入/结果。