从另一个ipynb文件导入ipynb文件?

182

交互式Python(ipython)非常棒,特别是在现场拼凑代码时...而且以一种易于调整的方式完成。

然而,似乎有趣的用例是使用多个ipython笔记本(ipynb文件)。 显然,笔记本电脑不应该与其他笔记本有关系,这是有道理的,但我希望导入其他ipynb文件。

我看到的唯一解决方法是将我的*.ipynb文件转换为*.py文件,然后可以将其导入我的笔记本。 如果我想真正推动代码重用(不是Python的核心原则吗?),让一个文件保存项目中的所有内容有点奇怪。

我错过了什么吗? ipython笔记本不支持此用例吗? 是否有另一种解决方案可以用于将ipynb文件导入到另一个笔记本中? 我很想继续使用ipynb,但它正在破坏我的工作流程:(


可能是重复问题:https://dev59.com/cnfZa4cB1Zd3GeqPRGeh - Warren Weckesser
3
你可以使用 --script 参数启动笔记本服务器以保存笔记本的 .py 副本。在 IPython 2.0 中,你将能够通过 %run 运行一个笔记本。我们仍在努力研究更好的代码重用机制。 - Thomas K
1
这个例子展示了如何将IPython笔记本作为模块导入,而不会导出重复的脚本。 - minrk
https://dev59.com/7WIj5IYBdhLWcg3whFQH,https://dev59.com/cnfZa4cB1Zd3GeqPRGeh和https://dev59.com/-2Ik5IYBdhLWcg3wIq5U都在询问同一个问题。 - Robie Basak
11个回答

212

5
运行MyOtherNotebook.ipynb对我来说已经足够了。(不含空格) - Florian H
9
请注意,这种方法将完全运行子笔记本。您可以添加一个检查__name__ == '__main__' and '__file__' not in globals()来验证是否在子笔记本中。(摘自https://blog.sicara.com/present-data-science-results-jupyter-notebook-import-into-another-108433bc8505) - Flavian Hautbois
15
抱歉,我无法找到文件 MyOtherNotebook.ipynb.py,请确认该文件是否存在并且路径是否正确。 - user3673
1
@Kocur4d感谢修复!有趣的是,当我尝试时(带引号),它对我起作用了,但文档中的示例没有任何引号。 - johndodo
5
如果有人遇到这个问题,也可以使用完整路径,例如 %run "/path/to/my/file/notebook.ipynb"。 - Jeremie
显示剩余9条评论

58

从命令提示符安装我的辅助库:

pip install import-ipynb

从你的笔记本导入它:

import import_ipynb

现在将您的 .ipynb 笔记本导入,就像它是一个 .py 文件一样

import TheOtherNotebook

这个python-ipynb模块只有一个文件,严格遵守Jupyter网站上官方指南

PS 它还支持像from A import foo, from A import *等功能

PPS 支持子目录:import A.B


1
@Crash pip install import-ipynb 也可以并且安装的是同一个包,但由于 Python 不允许编写 import import-ipynb,考虑到它只有一个文件,我认为 pip install import_ipynb 看起来更加一致。 - axil
3
import nbimporterÕÆīimport import_ipynbõ╣ŗķŚ┤µ£ēõ╗Ćõ╣łÕī║Õł½ÕÉŚ’╝¤ - Fractale
5
在我的Python 3的Jupyter中,这根本不起作用。 - Sebastialonso
需要导入笔记本的目录中是否有一个init.py文件? - Luk Aron
1
@axil。非常抱歉,我在执行过程中犯了一个错误,后来才知道。现在它已经正常工作了。非常感谢。 - Girish Kumar Chandora
显示剩余8条评论

55

运行

!pip install ipynb

然后将其他笔记本导入为

from ipynb.fs.full.<notebook_name> import *

或者

from ipynb.fs.full.<notebook_name> import <function_name>

确保所有笔记本都在同一个目录下。

编辑1:您可以在此处查看官方文档 - https://ipynb.readthedocs.io/en/stable/

另外,如果您只想从笔记本中导入类和函数定义(而不是顶层语句),则可以使用ipynb.fs.defs而不是ipynb.fs.full。全大写变量赋值也将得到评估。


4
如果我的文件名中有空格,会怎样? - Sameh
6
建议不要在文件名中使用任何空格。 - Malgo
6
请注意,在所描述的两种情况下,导入的笔记本将被完全执行。ipynb包还支持仅对定义进行部分执行。它是IPyhton的官方包,因此我相信这应该是被接受的答案。 - amka66
5
这个功能能否导入文件夹中的笔记本?比如说我的文件夹/笔记本.ipynb - bones225
1
@Malgo 执行后出现语言版本错误。 - Girish Kumar Chandora
显示剩余4条评论

26

从命令提示符安装ipynb

pip install import-ipynb

将其导入到你的笔记本文件中

import import_ipynb

现在使用常规的import命令导入您的文件

import MyOtherNotebook

最简单且能解释清楚的答案。谢谢! - Slim Shady
这需要导入笔记本的目录位置上有一个__init__.py文件吗? - Luk Aron
感谢您提供有关如何正确编写文档的线索。 - axil

7

%run YourNotebookfile.ipynb 正常工作;

如果您想导入特定的模块,只需在ipynb后添加import命令,例如YourNotebookfile.ipynb包含def Add()

然后您就可以使用它了。

%run YourNotebookfile.ipynb import Add

如果找不到文件,请尝试: %run ../YourNotebookfile.ipynb - NoamG

6

上述评论非常有用,但实施起来有些困难。您可以尝试以下步骤,我也尝试过它并且成功了:

  1. 从笔记本电脑中以PY文件格式下载该文件(您可以在“文件”选项卡中找到该选项)。
  2. 现在将下载的文件复制到Jupyter Notebook的工作目录中。
  3. 您现在已经准备好使用它了。只需将.PY文件导入ipynb文件即可。

嗯...我将callee.ipync转换为callee.py文件,然后将callee.py文件上传到与caller.ipync相同的文件夹下的笔记本中,在caller.ipync中只写了import callee,但就是无法工作。 - Elsa Lin
IPython的版本是5.1.0。 - Elsa Lin

6

你可以使用import nbimporter,然后import notebookName


+1,nbimporter 对我来说非常好用,而且可以使用 conda 安装:conda install -c conda-forge importnb - Zuku

3
问题在于notebook不是一个普通的python文件。导入.ipynb文件的步骤如下所述:导入notebook
我将代码粘贴在这里,如果你需要的话...你可以快速地复制和粘贴。请注意,在结尾处我有import primes语句。当然,你需要改变这个语句。我的文件名是primes.ipynb。从此时开始,你可以像平常一样使用该文件中的内容。
希望有更简单的方法,但这是直接从文档中摘录的。 注意:我使用的是jupyter而不是ipython。
import io, os, sys, types
from IPython import get_ipython
from nbformat import current
from IPython.core.interactiveshell import InteractiveShell


def find_notebook(fullname, path=None):
    """find a notebook, given its fully qualified name and an optional path

    This turns "foo.bar" into "foo/bar.ipynb"
    and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bar
    does not exist.
    """
    name = fullname.rsplit('.', 1)[-1]
    if not path:
        path = ['']
    for d in path:
        nb_path = os.path.join(d, name + ".ipynb")
        if os.path.isfile(nb_path):
            return nb_path
        # let import Notebook_Name find "Notebook Name.ipynb"
        nb_path = nb_path.replace("_", " ")
        if os.path.isfile(nb_path):
            return nb_path


class NotebookLoader(object):
    """Module Loader for Jupyter Notebooks"""
    def __init__(self, path=None):
        self.shell = InteractiveShell.instance()
        self.path = path

    def load_module(self, fullname):
        """import a notebook as a module"""
        path = find_notebook(fullname, self.path)

        print ("importing Jupyter notebook from %s" % path)

        # load the notebook object
        with io.open(path, 'r', encoding='utf-8') as f:
            nb = current.read(f, 'json')


        # create the module and add it to sys.modules
        # if name in sys.modules:
        #    return sys.modules[name]
        mod = types.ModuleType(fullname)
        mod.__file__ = path
        mod.__loader__ = self
        mod.__dict__['get_ipython'] = get_ipython
        sys.modules[fullname] = mod

        # extra work to ensure that magics that would affect the user_ns
        # actually affect the notebook module's ns
        save_user_ns = self.shell.user_ns
        self.shell.user_ns = mod.__dict__

        try:
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code' and cell.language == 'python':
                # transform the input to executable Python
                code = self.shell.input_transformer_manager.transform_cell(cell.input)
                # run the code in themodule
                exec(code, mod.__dict__)
        finally:
            self.shell.user_ns = save_user_ns
        return mod


class NotebookFinder(object):
    """Module finder that locates Jupyter Notebooks"""
    def __init__(self):
        self.loaders = {}

    def find_module(self, fullname, path=None):
        nb_path = find_notebook(fullname, path)
        if not nb_path:
            return

        key = path
        if path:
            # lists aren't hashable
            key = os.path.sep.join(path)

        if key not in self.loaders:
            self.loaders[key] = NotebookLoader(path)
        return self.loaders[key]

sys.meta_path.append(NotebookFinder())

import primes

2
Jupyter可以与现有或新的Python .py模块一起使用,完全没有问题。在Jupyter运行时,只需打开Spyder(或您选择的任何编辑器)以在.py文件中构建/修改模块类定义,然后根据需要将模块导入到Jupyter中即可。
使这一过程非常流畅的一件事情是使用autoreload魔术扩展。您可以在此处查看autoreload文档:

http://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html

这是自动重新加载模块的代码,每当它被修改时都会重新加载:
# autoreload sets up auto reloading of modified .py modules
import autoreload
%load_ext autoreload
%autoreload 2

请注意,我尝试了之前回复中提到的代码来模拟将 .ipynb 文件作为模块加载,并成功运行了它,但当您对 .ipynb 文件进行更改时,它会出现错误。看起来您需要重新启动 Jupyter 开发环境才能重新加载 .ipynb '模块',这对我来说是不可接受的,因为我正在对我的代码进行大量更改。

1
请确保在包中添加一个__init__.py文件,该文件位于您的其他.ipynb文件所在的位置。
这是在minrksyi提供的nbviewer链接之外的另一个要点。
我也遇到了类似的问题,然后我写了解决方案以及指向我的公共Google Drive文件夹的工作示例的链接:)
我的Stackoverflow帖子详细介绍了步骤和解决方案:

Jupyter Notebook: Import .ipynb file and access it's method in other .ipynb file giving error

希望这也能帮助其他人。 谢谢大家!

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