转换为(非) ipython 笔记本格式

IPython Notebook 附带 nbconvert,它可以将 出口笔记本转换成其他格式。但是如何将文本转换成相反的方向呢?我这样问是因为我已经有了不同格式的材料和良好的工作流程,但是我想利用一下 Notebook 的交互式环境。

一个可能的解决方案: 通过导入 .py文件可以创建一个笔记本,文档指出,当 nbconvert以 python 脚本的形式导出一个笔记本时,它会在注释中嵌入指令,这些注释可以用来重新创建笔记本。但是 免责声明提供了关于这种方法的局限性的信息,而且我能找到的任何地方都没有记录这种被接受的格式。(奇怪的是,在描述笔记本 JSON 格式的章节中显示了一个示例)。有人能提供更多的信息,或者更好的选择吗?

编辑(2016年3月1日) : 已接受的答案不再有效,因为出于某种原因,Notebook API 版本4不支持这种输入格式。我已经添加了一个自我回答演示如何使用当前(v4) API 导入笔记本电脑。(我并不是不接受当前的答案,因为它解决了我当时的问题,并指引我找到了我在自我回答中使用的资源。)

71036 次浏览

以下内容适用于 IPython3,但不适用于 IPython4。

IPythonAPI 具有读写笔记本文件的功能。您应该使用这个 API,而不是直接创建 JSON。例如,下面的代码片段将脚本 test.py转换为笔记本 test.ipynb

import IPython.nbformat.current as nbf
nb = nbf.read(open('test.py', 'r'), 'py')
nbf.write(nb, open('test.ipynb', 'w'), 'ipynb')

关于。Read 所理解的 py 文件,最好只查看解析器类 IPython.nbform.v3.nbpy.PyReader。代码可以在这里找到(它不是很大) :

Https://github.com/ipython/ipython/blob/master/jupyter_nbformat/v3/nbpy.py

编辑: 这个答案最初是为 IPyhton 3编写的。我不知道如何正确地使用 IPython4。下面是上面链接的更新版本,指向 IPython3.2.1发行版中的 nbpy.py版本:

Https://github.com/ipython/ipython/blob/rel-3.2.1/ipython/nbformat/v3/nbpy.py

基本上可以使用特殊注释(如 # <codecell># <markdowncell>)来分隔单个单元格。查看 PyReader.to_notebook中的 line.startswith语句以获得完整的列表。

Python 代码示例如何构建 IPython 笔记本 V4:

# -*- coding: utf-8 -*-
import os
from base64 import encodestring


from IPython.nbformat.v4.nbbase import (
new_code_cell, new_markdown_cell, new_notebook,
new_output, new_raw_cell
)


# some random base64-encoded *text*
png = encodestring(os.urandom(5)).decode('ascii')
jpeg = encodestring(os.urandom(6)).decode('ascii')


cells = []
cells.append(new_markdown_cell(
source='Some NumPy Examples',
))




cells.append(new_code_cell(
source='import numpy',
execution_count=1,
))


cells.append(new_markdown_cell(
source='A random array',
))


cells.append(new_raw_cell(
source='A random array',
))


cells.append(new_markdown_cell(
source=u'## My Heading',
))


cells.append(new_code_cell(
source='a = numpy.random.rand(100)',
execution_count=2,
))
cells.append(new_code_cell(
source='a = 10\nb = 5\n',
execution_count=3,
))
cells.append(new_code_cell(
source='a = 10\nb = 5',
execution_count=4,
))


cells.append(new_code_cell(
source=u'print "ünîcødé"',
execution_count=3,
outputs=[new_output(
output_type=u'execute_result',
data={
'text/plain': u'<array a>',
'text/html': u'The HTML rep',
'text/latex': u'$a$',
'image/png': png,
'image/jpeg': jpeg,
'image/svg+xml': u'<svg>',
'application/json': {
'key': 'value'
},
'application/javascript': u'var i=0;'
},
execution_count=3
),new_output(
output_type=u'display_data',
data={
'text/plain': u'<array a>',
'text/html': u'The HTML rep',
'text/latex': u'$a$',
'image/png': png,
'image/jpeg': jpeg,
'image/svg+xml': u'<svg>',
'application/json': {
'key': 'value'
},
'application/javascript': u'var i=0;'
},
),new_output(
output_type=u'error',
ename=u'NameError',
evalue=u'NameError was here',
traceback=[u'frame 0', u'frame 1', u'frame 2']
),new_output(
output_type=u'stream',
text='foo\rbar\r\n'
),new_output(
output_type=u'stream',
name='stderr',
text='\rfoo\rbar\n'
)]
))


nb0 = new_notebook(cells=cells,
metadata={
'language': 'python',
}
)


import IPython.nbformat as nbf
import codecs
f = codecs.open('test.ipynb', encoding='utf-8', mode='w')
nbf.write(nb0, f, 4)
f.close()

通过 VolodimirKopey 的示例,我整理了一个简单的脚本来转换。通过出口从一个。Ipynb 回到 V4。爱因布。

在编辑(在适当的 IDE 中) a 时,我将这个脚本拼凑在一起。我已经导出了一个笔记本电脑,我想回到笔记本电脑运行它的细胞。

该脚本只处理代码单元格。

import nbformat
from nbformat.v4 import new_code_cell,new_notebook


import codecs


sourceFile = "changeMe.py"     # <<<< change
destFile = "changeMe.ipynb"    # <<<< change




def parsePy(fn):
""" Generator that parses a .py file exported from a IPython notebook and
extracts code cells (whatever is between occurrences of "In[*]:").
Returns a string containing one or more lines
"""
with open(fn,"r") as f:
lines = []
for l in f:
l1 = l.strip()
if l1.startswith('# In[') and l1.endswith(']:') and lines:
yield "".join(lines)
lines = []
continue
lines.append(l)
if lines:
yield "".join(lines)


# Create the code cells by parsing the file in input
cells = []
for c in parsePy(sourceFile):
cells.append(new_code_cell(source=c))


# This creates a V4 Notebook with the code cells extracted above
nb0 = new_notebook(cells=cells,
metadata={'language': 'python',})


with codecs.open(destFile, encoding='utf-8', mode='w') as f:
nbformat.write(nb0, f, 4)

没有保证,但对我很有效

我擅自修改了 P · 托卡特利和亚历克西斯的代码这样它就能和魅惑力和蜘蛛一样的细胞标记一起工作并在 Github上释放出来。

由于已接受答案中的代码不再有效,我添加了这个自我答案,它显示了如何使用当前(v4) API 导入到笔记本中。

输入格式

IPython Notebook API 的版本2和版本3可以导入带有特殊结构注释的 python 脚本,并根据需要将其分解为单元格。下面是一个示例输入文件(原始文档 给你)。前两行被忽略,并且是可选的。(实际上,读取器将忽略文件中任何地方的 coding:<nbformat>行。)

# -*- coding: utf-8 -*-
# <nbformat>3.0</nbformat>


# <markdowncell>


# The simplest notebook. Markdown cells are embedded in comments,
# so the file is a valid `python` script.
# Be sure to **leave a space** after the comment character!


# <codecell>


print("Hello, IPython")


# <rawcell>


# Raw cell contents are not formatted as markdown

(API 还接受过时的指令 <htmlcell><headingcell level=...>,它们会立即转换为其他类型。)

如何进口

由于某些原因,NotebookAPI 的版本4不支持这种格式。它仍然是一种很好的格式,所以通过导入到版本3并进行升级来支持它是值得的。原则上是只有两行代码,外加 i/o:

from IPython.nbformat import v3, v4


with open("input-file.py") as fpin:
text = fpin.read()


nbook = v3.reads_py(text)
nbook = v4.upgrade(nbook)  # Upgrade v3 to v4


jsonform = v4.writes(nbook) + "\n"
with open("output-file.ipynb", "w") as fpout:
fpout.write(jsonform)

但别这么快!事实上,笔记本 API 有一个讨厌的 bug: 如果输入中的最后一个单元格是减价单元格,v3.reads_py()将丢失它。最简单的解决办法是在最后添加一个假的 <markdown>单元: bug 会删除它,这样大家都满意了。因此,在将 text传递给 v3.reads_py()之前,请执行以下操作:

text += """
# <markdowncell>


# If you can read this, reads_py() is no longer broken!
"""

我为 vscode 写了一个扩展,可能会有帮助。它将 python 文件转换为 ipython 笔记本。这是在早期阶段,所以如果有任何错误发生,随时提交一个问题。

朱庇特笔记本转换器

您可以使用来自 https://github.com/sklam/py2nb的脚本 py2nb

您将不得不为您的 * 使用某种语法。Py,但是它的使用相当简单(请看“ sample”文件夹中的示例)

很老的问题了,我知道。但是 jupytext(也可以在 皮皮上使用)可以从 ipynb转换成多种格式。

当安装 jupytext时,您可以使用

$ jupytext --to notebook test.py

以便生成 test.ipynb

jupytext有许多更有趣的特性,在使用笔记本电脑时可以派上用场。


下面是 最近的一个问题关于这个话题的报道。

希望我还来得及。

我刚刚在 PyPI 上发布了一个名为 P2j的 Python 包。这个包从 Python 源代码 .py创建一个 Jupiter 笔记本 .ipynb

pip install p2j
p2j script.py

.py文件生成的 Jupiter 笔记本示例:

Example of .ipynb generated from a .py file

PyPI: https://pypi.org/project/p2j/

GitHub: https://github.com/remykarem/python2jupyter

对@p-tocceli 答案的一些改进。 现在,它还可以恢复标记单元格。此外,它还可以修剪每个单元格的空悬挂线。

    import nbformat
from nbformat.v4 import new_code_cell,new_markdown_cell,new_notebook


import codecs


sourceFile = "changeMe.py"     # <<<< change
destFile = "changeMe.ipynb"    # <<<< change




def parsePy(fn):
""" Generator that parses a .py file exported from a IPython notebook and
extracts code cells (whatever is between occurrences of "In[*]:").
Returns a string containing one or more lines
"""
with open(fn,"r") as f:
lines = []
for l in f:
l1 = l.strip()
if l1.startswith('# In[') and l1.endswith(']:') and lines:
yield ("".join(lines).strip(), 0)
lines = []
continue
elif l1.startswith('# ') and l1[2:].startswith('#') and lines:
yield ("".join(lines).strip(), 0)


yield (l1[2:].strip(), 1)
lines = []
continue
lines.append(l)
if lines:
yield ("".join(lines).strip(), 0)


# Create the code cells by parsing the file in input
cells = []
for c, code in parsePy(sourceFile):
if len(c) == 0:
continue
if code == 0:
cells.append(new_code_cell(source=c))
elif code == 1:
cells.append(new_markdown_cell(source=c))


# This creates a V4 Notebook with the code cells extracted above
nb0 = new_notebook(cells=cells,
metadata={'language': 'python',})


with codecs.open(destFile, encoding='utf-8', mode='w') as f:
nbformat.write(nb0, f, 4)