转换为(不是来自)ipython Notebook 格式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23292242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting to (not from) ipython Notebook format
提问by alexis
IPython Notebook comes with nbconvert
, which can exportnotebooks to other formats. But how do I convert text in the opposite direction? I ask because I already have materials, and a good workflow, in a different format, but I would like to take advantage of Notebook's interactive environment.
IPython Notebook 自带nbconvert
,可以将笔记本导出为其他格式。但是我如何以相反的方向转换文本?我问是因为我已经有了不同格式的材料和良好的工作流程,但我想利用 Notebook 的交互环境。
A likely solution: A notebook can be created by importing a .py
file, and the documentation states that when nbconvert
exports a notebook as a python script, it embeds directives in comments that can be used to recreate the notebook. But the information comes with a disclaimerabout the limitations of this method, and the accepted format is not documented anywhere that I could find. (A sample is shown, oddly enough, in the section describing notebook's JSON format). Can anyone provide more information, or a better alternative?
一个可能的解决方案:可以通过导入.py
文件来创建笔记本,文档指出,当nbconvert
将笔记本导出为 python 脚本时,它会在可用于重新创建笔记本的注释中嵌入指令。但是该信息附带了关于此方法局限性的免责声明,并且在我能找到的任何地方都没有记录可接受的格式。(奇怪的是,在描述 notebook 的JSON 格式的部分中显示了一个示例)。谁能提供更多信息或更好的选择?
Edit (1 March 2016):The accepted answer no longer works, because for some reason this input format is not supported by version 4 of the Notebook API. I have added a self-answershowing how to import a notebook with the current (v4) API. (I am not un-accepting the current answer, since it solved my problem at the time and pointed me to the resources I used in my self-answer.)
编辑(2016 年 3 月 1 日):接受的答案不再有效,因为出于某种原因,Notebook API 的第 4 版不支持此输入格式。 我添加了一个自我回答,展示了如何使用当前 (v4) API 导入笔记本。(我并不是不接受当前的答案,因为它当时解决了我的问题,并向我指出了我在自我回答中使用的资源。)
采纳答案by CliffordVienna
The following works for IPython 3, but not IPython 4.
以下适用于 IPython 3,但不适用于 IPython 4。
The IPython API has functions for reading and writing notebook files. You should use this API and not create JSON directly. For example, the following code snippet converts a script test.py
into a notebook test.ipynb
.
IPython API 具有读取和写入笔记本文件的功能。您应该使用此 API,而不是直接创建 JSON。例如,以下代码片段将脚本test.py
转换为 notebook test.ipynb
。
import IPython.nbformat.current as nbf
nb = nbf.read(open('test.py', 'r'), 'py')
nbf.write(nb, open('test.ipynb', 'w'), 'ipynb')
Regarding the format of the .py file understood by nbf.read it is best to simply look into the parser class IPython.nbformat.v3.nbpy.PyReader. The code can be found here (it is not very large):
关于 nbf.read 理解的 .py 文件的格式,最好简单地查看解析器类 IPython.nbformat.v3.nbpy.PyReader。代码可以在这里找到(它不是很大):
https://github.com/ipython/ipython/blob/master/jupyter_nbformat/v3/nbpy.py
https://github.com/ipython/ipython/blob/master/jupyter_nbformat/v3/nbpy.py
Edit:This answer was originally written for IPyhton 3. I don't know how to do this properly with IPython 4. Here is an updated version of the link above, pointing to the version of nbpy.py
from the IPython 3.2.1 release:
编辑:此答案最初是为 IPyhton 3 编写的。我不知道如何使用 IPython 4 正确执行此操作。这是上面链接的更新版本,指向nbpy.py
IPython 3.2.1 版本中的版本:
https://github.com/ipython/ipython/blob/rel-3.2.1/IPython/nbformat/v3/nbpy.py
https://github.com/ipython/ipython/blob/rel-3.2.1/IPython/nbformat/v3/nbpy.py
Basically you use special comments such as # <codecell>
or # <markdowncell>
to separate the individual cells. Look at the line.startswith
statements in PyReader.to_notebook
for a complete list.
基本上,您使用特殊注释(例如# <codecell>
或 )# <markdowncell>
来分隔单个单元格。查看 中的line.startswith
语句以PyReader.to_notebook
获取完整列表。
回答by Volodimir Kopey
Python code example how to build IPython notebook V4:
Python 代码示例如何构建 IPython notebook 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()
回答by P.Toccaceli
Given the example by Volodimir Kopey, I put together a bare-bones script to convert a .py obtained by exporting from a .ipynb back into a V4 .ipynb.
鉴于 Volodimir Kopey 的示例,我整理了一个基本脚本,将通过从 .ipynb 导出的 .py 转换回 V4 .ipynb。
I hacked this script together when I edited (in a proper IDE) a .py I had exported from a Notebook and I wanted to go back to Notebook to run it cell by cell.
当我编辑(在适当的 IDE 中)一个从 Notebook 导出的 .py 时,我一起破解了这个脚本,我想回到 Notebook 逐个单元地运行它。
The script handles only code cells. The exported .py does not contain much else, anyway.
该脚本仅处理代码单元格。无论如何,导出的 .py 不包含太多其他内容。
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)
No guarantees, but it worked for me
没有保证,但它对我有用
回答by John Smith
回答by alexis
Since the code in the accepted answer does not work anymore, I have added this self-answer that shows how to import into a notebook with the current (v4
) API.
由于接受的答案中的代码不再起作用,我添加了这个自我答案,展示了如何使用当前 ( v4
) API导入笔记本。
Input format
输入格式
Versions 2 and 3 of the IPython Notebook API can import a python script with special structuring comments, and break it up into cells as desired. Here's a sample input file (original documentation here). The first two lines are ignored, and optional. (In fact, the reader will ignore coding:
and <nbformat>
lines anywhere in the file.)
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
(The API also accepts the obsolete directives <htmlcell>
and <headingcell level=...>
, which are immediately transformed to other types.)
(API 还接受过时的指令<htmlcell>
and <headingcell level=...>
,它们会立即转换为其他类型。)
How to import it
如何导入
For some reason, this format is not supported by version 4 of the Notebook API. It's still a nice format, so it's worth the trouble to support it by importing into version 3 and upgrading. In principleit's just two lines of code, plus i/o:
出于某种原因,Notebook API 的第 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)
But not so fast! In fact, the notebook API has a nasty bug: If the last cell in the input is a markdown cell, v3.reads_py()
will lose it. The simplest work-around is to tack on a bogus <markdown>
cell at the end: The bug will delete it, and everyone is happy. So do the following before you pass text
to v3.reads_py()
:
但没那么快!实际上,notebook API 有一个讨厌的 bug:如果输入中的最后一个单元格是 markdown 单元格,v3.reads_py()
则会丢失它。最简单的解决方法是在最后添加一个伪造的<markdown>
单元格:错误将删除它,每个人都很高兴。因此,在传递text
给之前,请执行以下操作v3.reads_py()
:
text += """
# <markdowncell>
# If you can read this, reads_py() is no longer broken!
"""
回答by YigitOzgumus
I wrote an extension for vscode that might help. It converts the python files to ipython notebooks. It's in early stages so if any error occurs, feel free to submit an issue.
我为 vscode 编写了一个可能有帮助的扩展。它将 python 文件转换为 ipython 笔记本。它处于早期阶段,因此如果发生任何错误,请随时提交问题。
回答by valbarriere
You can use the script py2nb from https://github.com/sklam/py2nb
您可以使用https://github.com/sklam/py2nb 中的脚本 py2nb
You will have to use a certain syntax for your *.py but it's rather simple to use (look at the example in the 'samples' folder)
您必须为 *.py 使用某种语法,但使用起来相当简单(查看“samples”文件夹中的示例)
回答by hiro protagonist
very old question, i know. but there is jupytext
(also available on pypi) that can convert from ipynb
to several formats and back.
很老的问题,我知道。但是有jupytext
(也可在pypi 上使用)可以转换ipynb
为多种格式并返回。
when jupytext
is installed you can use
什么时候jupytext
安装你可以使用
$ jupytext --to notebook test.py
in order to generate test.ipynb
.
为了生成test.ipynb
.
jupytext
has a lot more interesting features that can come in handy when working with notebooks.
jupytext
有更多有趣的功能,可以在使用笔记本时派上用场。
here is a more recent questionon that topic.
这是关于该主题的最新问题。
回答by Raimi bin Karim
Hope I'm not too late.
希望我还不算太晚。
I just published a Python package on PyPI called p2j. This package creates a Jupyter notebook .ipynb
from a Python source code .py
.
我刚刚在 PyPI 上发布了一个名为p2j的 Python 包。这个包.ipynb
从 Python 源代码创建一个 Jupyter 笔记本.py
。
pip install p2j
p2j script.py
Example of a Jupyter notebook generated from a .py
file:
从.py
文件生成的 Jupyter 笔记本示例:
PyPI: https://pypi.org/project/p2j/
PyPI:https://pypi.org/project/p2j/
回答by Konstantin Avchaciov
Some improvement to @p-toccaceli answer. Now, it also restores markdown cells. Additionally, it trims empty hanging lines for each cell.
对@p-toccaceli 的回答进行了一些改进。现在,它还恢复了 Markdown 单元格。此外,它会修剪每个单元格的空挂线。
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)