交互式 Python (ipython) 简直太棒了,尤其是当您在运行中将事物拼凑在一起时……并且以一种很容易返回的方式进行操作。
然而,有趣的是拥有多个 ipython 笔记本(ipynb 文件)的用例。显然,笔记本似乎不应该与其他笔记本有关系,这是有道理的,除了我想导入其他 ipynb 文件。
我看到的唯一解决方法是将我的 *.ipynb 文件转换为 *.py 文件,然后可以将其导入我的笔记本中。让一个文件保存项目中的所有内容有点奇怪,特别是如果我想真正推动代码重用(这不是 python 的核心原则吗?)。
我错过了什么吗?这不是 ipython 笔记本支持的用例吗?我可以使用另一种解决方案将 ipynb 文件导入另一个笔记本吗?我很想继续使用 ipynb,但它现在真的打乱了我的工作流程:(
--script
启动笔记本服务器以保存笔记本的 .py 副本。在 IPython 2.0 中,您将能够%run
一个笔记本。我们仍在制定更好的代码重用机制。
从命令提示符安装我的助手库:
pip install import-ipynb
从您的笔记本中导入它:
import import_ipynb
现在导入您的 .ipynb 笔记本,就好像它是一个 .py 文件一样
import TheOtherNotebook
这个 python-ipynb
模块只是一个文件,它严格遵守 jupyter 站点上的 official howto。
PS 它还支持 from A import foo
、from A import *
等
PPS 适用于子目录:import A.B
pip install import-ipynb
也可以工作并安装相同的包,但由于 python 不允许您编写 import import-ipynb
并且考虑到它只是一个文件,所以 pip install import_ipynb
对我来说看起来更一致。
import nbimporter
和 import import_ipynb
之间有什么区别吗?
跑
!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/
另外,如果您只想导入 class &来自笔记本的函数定义(而不是顶级语句),您可以使用 ipynb.fs.defs
而不是 ipynb.fs.full
。完整的大写变量赋值也将被评估。
ipynb
包还支持仅部分执行定义。它是 IPyhton 的官方软件包,所以我相信这应该是公认的答案。
MyFolder/book.ipynb
从命令提示符安装 ipynb
pip install import-ipynb
在您的笔记本文件中导入
import import_ipynb
现在使用常规导入命令导入您的文件
import MyOtherNotebook
您可以使用 import nbimporter
然后 import notebookName
conda install -c conda-forge importnb
上面提到的注释非常有用,但实施起来有点困难。您可以尝试以下步骤,我也尝试过并且有效:
以 PY 文件格式从您的笔记本下载该文件(您可以在“文件”选项卡中找到该选项)。现在将下载的文件复制到 Jupyter Notebook 的工作目录中,您现在可以使用它了。只需将 .PY 文件导入到 ipynb 文件中
import callee
,就无法工作。
%run YourNotebookfile.ipynb 工作正常;
如果要导入特定模块,则只需在 ipynb 之后添加导入命令,即 YourNotebookfile.ipynb 具有 def Add()
那么你可以使用它
%run YourNotebookfile.ipynb import Add
问题是笔记本不是普通的 python 文件。导入 .ipynb
文件的步骤概述如下:Importing 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
将 Jupyter 与现有或新的 Python .py 模块一起使用完全没有问题。在 Jupyter 运行的情况下,只需启动 Spyder(或您选择的任何编辑器)以在 .py 文件中构建/修改模块类定义,然后根据需要将模块导入 Jupyter。
使这真正无缝的一件事是使用自动重载魔法扩展。您可以在此处查看 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 '模块',这对我来说是不可接受的,因为我对我的代码进行了大量更改。
请确保您还在所有其他 .ipynb 文件所在的包中添加一个 __init__.py
文件。
这是对上面 minrk
和 syi
提供的 nbviewer 链接的补充。
我也遇到了一些类似的问题,然后我编写了解决方案以及指向我的公共谷歌驱动器文件夹的链接,该文件夹有一个工作示例:)
我的 Stackoverflow 帖子分步实验和解决方案:
Jupyter Notebook: Import .ipynb file and access it's method in other .ipynb file giving error
希望这对其他人也有帮助。谢谢大家!
虽然“%run childNotebook.ipynb”命令是一个非常简单且有用的解决方案(如上一个答案中所述),但当子文件也使用另一个“%run grandChildNotebook.ipynb”时,您应该谨慎使用它,但位于另一个目录中!它可能导致文件重复运行,并且也容易出错(因为子进程不再使用与其父进程相同的路径,而在运行时,Jupyter 假定它会这样做!)
为了解决上述问题,一个解决方案可能是这样的:在导入任何文件之前,首先检查当前目录的位置,然后根据它采取行动。这是一个例子:
if 'myFolder' in os.getcwd():
%run graindChildNotebook.ipynb
else:
%run myFolder/grandChildNotebook.ipynb
在上面的示例中,首先检查我们是否在“myFolder”目录中。如果是这样,我们会发现“grandChildNotebook”在同一个目录中,正常运行就足够了。否则,我们需要通过添加此文件所在文件夹的名称来运行它。
请注意,这只是一个示例,您应该根据您的情况进行个性化的解决方案!
__name__ == '__main__' and '__file__' not in globals()
以验证您是否在子笔记本中。 (来自 blog.sicara.com/…)u'MyOtherNotebook.ipynb.py'
。