在Jupyter Notebook中导入模块时出现“模块未找到”的错误

44

我有以下这个包(和工作目录):

WorkingDirectory--
                 |--MyPackage--
                 |            |--__init__.py
                 |            |--module1.py
                 |            |--module2.py
                 |
                 |--notebook.ipynb

__init__.py中我有:

import module1
import module2

如果我尝试将MyPackage导入到我的笔记本中:

import MyPackage as mp 

我会得到ModuleNotFoundError:找不到名为 'module1' 的模块的错误。 但是,如果我在笔记本外部执行脚本:如果我在相同的目录中创建test.py并执行与笔记本中相同的操作,则导入可以正常工作。 如果我在__init__.py中使用完全限定名称(import MyPackage.module1),它将在笔记本中运行。

不同导入行为的原因是什么?

我已确认笔记本的工作目录为WorkingDirectory

---更新---------

精确错误为:

C:\Users\Me\Documents\Working Directory\MyPackage\__init__.py in <module>()
---> 17 import module1

ModuleNotFoundError: No module named 'module1'

我的问题与可能的重复问题略有不同:

  1. 笔记本能够找到该软件包,但只是无法加载模块。这是通过将 module1 替换为 MyPackage.module1 发现的,并且表明可能与 PATH 无关。

  2. 我进入了 WorkingDirectory 并在那里启动了服务器。工作目录应该是包含我的软件包的文件夹。


可能是"ImportError: No module named" when trying to run Python script的重复问题。 - Louise Davies
@LouiseDavies 我更新了我的问题来解决重复问题。 - Ryan
我曾经遇到过类似的问题,它连接到了一些旧内核,这些内核并没有所有的软件包;确保你一次只连接一个内核,并且它连接到默认端口8888。 - reim
https://stackoverflow.com/a/57903029/6200607 对我有用 - undefined
9个回答

34

我很确定这个问题是相关的,那里的答案会对你有所帮助:https://dev59.com/I2Up5IYBdhLWcg3wGEoR#15622021

简而言之,笔记本服务器的cwd始终是启动服务器的基本路径,不管运行import os os.getcwd()得到了什么结果。使用import sys sys.path.append("/path/to/your/module/folder")

我在与你指定的相同结构中运行了一些虚拟模块,在修改sys.path之前,它无法运行,但在修改之后就可以了。


2
你是指将 WorkingDirectory 添加到 PATH 还是 WorkingDirectory/MyPackage?后者有效,但前者无效。这是预期的行为吗?如果问题出在 PATH 上,为什么在 init.py 中使用完全限定名称可以解决问题? - Ryan

7
了解这两个函数,您的问题将会得到解决。
#list the current work dir
os.getcwd()
#change the current work dir
os.chdir()

更改路径并导入模块,尽情享受。有时会出现无法运行的情况,请尝试以下方法。

import sys
# sys.path is a list of absolute path strings
sys.path.append('/path/to/application/app/folder')

import file

-, -


1
os.chdir需要一个参数。 - nixon

4
最好的解决方法是创建一个虚拟环境并将内核指向该虚拟环境:
步骤:
1. 运行命令:python -m venv venv 2. 运行命令:source venv/bin/activate 3. 运行命令:ipython kernel install --user --name=venv 4. 运行命令:jupyter lab 5. 转到 jupyter lab -> kernel -> change kernel -> 从下拉列表中添加 venv 现在,如果你的虚拟环境中已安装了所需包,jupyter lab也能看到这个包,并且导入该包时不会出现任何问题。

这是最通用的解决方案。 - undefined

3

如果你在 jupyter环境 中遇到了 模块未找到 的问题,你需要在 jupyter 环境中安装它,而不是通过命令提示符进行安装。

在 jupyter 上可以使用以下命令(适用于 Windows):

!pip install 模块名

之后就可以轻松导入和使用该模块了。 每当你想告诉 jupyter 这是系统命令时,都应该在命令前加上 ( ! )。


1
请勿在多个问题上发布重复答案(这里这里)。一个答案就足够了。请参阅是否可以将重复答案添加到多个问题中? - Sven Eberth

1

我的问题是在使用Vs Code时,我使用了错误的conda环境。

输入您的conda环境

conda activate **enviroment_name**

要检查模块的安装位置,您可以通过编写python或python3进入Python交互模式。然后导入cv2模块。

import cv2

然后查看此模块的安装位置

print(cv2.__file__)

您将看到模块的安装路径。我的问题是我的 VS Code 内核设置为错误的环境。这可以在 VS Code 的右上角进行更改。

希望这可以帮助到您。


0

对我来说,迄今为止最好的解决方案是为每个工作环境都设置一个内核。然后,定义了该内核后,您只需更新此内核的环境变量以查看您的项目文件夹,其中包含您的模块。

步骤(使用pip):

  1. pip install ipykernel(如果尚未安装)
  2. source activate <your environment name>
  3. python -m ipykernel install --user --name <your environment name> --display-name "<a display name>"(其中是您要为内核命名的名称,仅是jupyter用于显示的名称。
  4. 运行上述命令后,它将输出内核配置文件的位置。例如:C:\Users\<your user name>\AppData\Roaming\jupyter\kernels\<selected environment name>。转到此文件夹并打开kernel.json文件。
  5. 在此文件中添加以下条目:
"env": {
   "PYTHONPATH": "${PYTHONPATH};<the path to your project with your modules>
 }

关于内核安装命令的好参考资料在这里


0

您可以通过安装import_ipynb包来实现。

pip install import_ipynb

假设你想在A.ipynb中导入B.ipynb,你可以按照以下步骤进行操作:
在A.ipynb中:
import import_ipynb
import B as b

然后您可以在A中使用B.ipynb的所有函数。


0

当我将我的日志移动到一个新目录时,Jupyter lab服务器正在运行,这种情况发生了。该日志的导入失败了,但是当我在同一目录中创建了一个新的日志,并使用相同的导入时,它起作用了。为了解决这个问题,我:

  1. 进入项目的根目录。
  2. 搜索所有标记为“pycache”的文件夹。
  3. 删除在我的根目录和子文件夹中找到的所有“pycache”文件夹。
  4. 重新启动Jupyter lab服务器。

一旦Jupyter lab重新启动并编译您的代码,“pycache”文件夹将被重新生成。此外,pycache文件夹有两个前导和尾随的“_”,但stackoverflow会格式化没有它们的pycache。


-1
原因是您的MyPackage/__init__.py是从当前工作目录运行的。例如,在这种情况下,从WorkingDirectory运行。这意味着解释器无法找到名为module1的模块,因为它不位于当前或全局包目录中。
有几个解决方法。例如,您可以像这样临时覆盖当前工作目录:
cwd = os.getcwd()
csd = __path__[0]
os.chdir(csd)

然后,在完成所有包初始化操作,如import module1之后,使用os.chdir(cwd)恢复“调用者”的工作目录。

对我来说,这是一种相当糟糕的方法,因为例如,如果在初始化操作中引发异常,则不会恢复工作目录。您需要使用try..except语句来解决这个问题。

另一种方法是使用相对导入。有关更多详细信息,请参阅文档

这里是一个MyPackage/__init__.py的示例,适用于您的示例:

from .module1 import *

但是它有一些缺点,这些缺点通常是通过实证而不是文档发现的。例如,您不能编写类似于import .module1的代码。


更新: 我发现这个异常甚至在常规的 python 控制台中运行 import MyPackage 时也会被触发。而不是在 IPython 或 Jupyter Notebook 中。所以这似乎不是 IPython 本身的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接