附带IPython笔记本nbconvert
,可以将笔记本导出为其他格式.但是如何以相反的方向转换文本?我问,因为我已经拥有不同格式的材料和良好的工作流程,但我想利用Notebook的交互式环境.
一个可能的解决方案:可以通过导入.py
文件来创建笔记本,并且文档指出当nbconvert
将笔记本导出为python脚本时,它会在可用于重新创建笔记本的注释中嵌入指令.但是这些信息附带了关于此方法的局限性的免责声明,并且在我能找到的任何地方都没有记录可接受的格式.(奇怪的是,在描述笔记本的JSON格式的部分中显示了一个示例).任何人都可以提供更多信息,或更好的选择吗?
编辑(2016年3月1日):已接受的答案不再有效,因为出于某种原因,Notebook API的第4版不支持此输入格式. 我添加了一个自我答案,展示了如何使用当前(v4)API导入笔记本.(我不是不接受当前的答案,因为它解决了我当时的问题并指出了我在自我回答中使用的资源.)
以下适用于IPython 3,但不适用于IPython 4.
IPython API具有读写笔记本文件的功能.您应该使用此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')
关于nbf.read理解的.py文件格式,最好只查看解析器类IPython.nbformat.v3.nbpy.PyReader.代码可以在这里找到(它不是很大):
https://github.com/ipython/ipython/blob/master/jupyter_nbformat/v3/nbpy.py
编辑:这个答案最初是为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
基本上,您使用特殊注释,例如#
或#
分隔单个单元格.查看line.startswith
语句以PyReader.to_notebook
获取完整列表.
由于接受的答案中的代码不再起作用,我添加了这个自我答案,显示了如何使用current(v4
)API 导入到笔记本中.
IPython Notebook API的第2版和第3版可以导入带有特殊结构注释的python脚本,并根据需要将其分解为单元格.这是一个示例输入文件(此处为原始文档).前两行被忽略,并且是可选的.(实际上,读者会忽略coding:
并
排列文件中的任何位置.)
# -*- coding: utf-8 -*- #3.0 ## 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! # print("Hello, IPython") # # Raw cell contents are not formatted as markdown
(API还接受过时指令
和
,其被立即转化为其它类型的).
出于某种原因,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)
但不是那么快!实际上,笔记本API有一个令人讨厌的错误:如果输入中的最后一个单元格是降价单元格,v3.reads_py()
则会丢失它.最简单的解决方法是
在最后处理一个虚假的单元:bug将删除它,每个人都很高兴.在text
转到之前,请执行以下操作v3.reads_py()
:
text += """ ## If you can read this, reads_py() is no longer broken! """
很老的问题,我知道.但是jupytext
(也可以在pypi上使用)可以转换ipynb
为多种格式并返回.
当jupytext
安装时,您可以使用
$ jupytext --to notebook test.py
为了生成test.ipynb
.
jupytext
有更多有趣的功能,可以在使用笔记本电脑时派上用场.
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'', 'text/html': u'The HTML rep', 'text/latex': u'$a$', 'image/png': png, 'image/jpeg': jpeg, 'image/svg+xml': u'
考虑到Volodimir Kopey的例子,我整理了一个简单的脚本,将.ipynb导出的.py转换回V4 .ipynb.
当我编辑(在适当的IDE中)我从笔记本导出的.py时,我一起攻击了这个脚本,我想回到Notebook,逐个单元地运行它.
该脚本仅处理代码单元格.无论如何,导出的.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)
没有保证,但它对我有用