转换为(不是来自)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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:39:49  来源:igfitidea点击:

Converting to (not from) ipython Notebook format

pythonipythonipython-notebookjupyter-notebook

提问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 .pyfile, and the documentation states that when nbconvertexports 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.pyinto 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.pyfrom the IPython 3.2.1 release:

编辑:此答案最初是为 IPyhton 3 编写的。我不知道如何使用 IPython 4 正确执行此操作。这是上面链接的更新版本,指向nbpy.pyIPython 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.startswithstatements in PyReader.to_notebookfor 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

Took the liberty of taking and modifying the code of P.Toccateli and alexis so that it will also work with pycharm and spyder like cell markers and released it on github.

冒昧地修改了 P.Toccateli 和 alexis 的代码,使它也能像细胞标记一样与 pycharm 和 spyder 一起工作,并在github上发布。

回答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 textto 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 笔记本。它处于早期阶段,因此如果发生任何错误,请随时提交问题。

Jupyter Notebook Converter

Jupyter 笔记本转换器

回答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 ipynbto several formats and back.

很老的问题,我知道。但是有jupytext(也可在pypi 上使用)可以转换ipynb为多种格式并返回。

when jupytextis installed you can use

什么时候jupytext安装你可以使用

$ jupytext --to notebook test.py

in order to generate test.ipynb.

为了生成test.ipynb.

jupytexthas 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 .ipynbfrom 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 .pyfile:

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

Example of .ipynb generated from a .py file

从 .py 文件生成的 .ipynb 示例

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

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

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

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

回答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)