27

我看过一些 iPython 开发人员关于如何将 ipython 笔记本转换 为博客文章、pdf甚至整本书的演讲(大约 43 分钟)。PDF-to-X 转换器会解释用 markdown 或代码编写的iPython 单元格,并在一个步骤中输出一个新格式化的文档。

我的问题是我想生成一个大型文档,其中许多图形和部分都是以编程方式生成的 - 类似这样。为了使用上述方法在 iPython 中工作,我需要能够编写一个函数来编写其他 iPython-Code-Blocks。这种能力存在吗?

#some pseudocode to give an idea
for variable in list:
    image = make_image(variable)
    write_iPython_Markdown_Cell(variable)
    write_iPython_Image_cell(image)

我认为这可能有用,所以我想知道是否:

  1. 通过 iPython 生成 iPython 单元是可能的
  2. 如果有理由认为这是一个坏主意,我应该坚持使用模板库(Jinja)等“经典”解决方案。

谢谢,扎克cp

编辑:根据 Thomas 的建议,我在ipython 邮件列表上发布了一些关于这个想法可行性的反馈。简而言之 - 有一些技术上的困难使这个想法对于最初的想法不太理想。对于想要生成 markdown 单元和相应图像/表格的重复报告,通过 ipython 内核/浏览器工作比直接使用 Jinja 等模板系统生成报告要复杂得多。

4

10 回答 10

24

Fernando Perez这里有一个 Notebook gist ,演示了如何以编程方式创建新单元格。请注意,您还可以传入元数据,因此如果您正在生成报告并希望将笔记本变成幻灯片,您可以轻松地指示单元格是否应该是幻灯片、子幻灯片、片段等。

您可以添加任何类型的单元格,因此您现在想要的很简单(尽管可能不是在提出问题时!)。例如,这样的东西(未经测试的代码)应该可以工作:

from IPython.nbformat import current as nbf

nb = nbf.new_notebook()

cells = []

for var in my_list:
    # Assume make_image() saves an image to file and returns the filename
    image_file = make_image(var)
    text = "Variable: %s\n![image](%s)" % (var, image_file)
    cell = nbf.new_text_cell('markdown', text)
    cells.append(cell)

nb['worksheets'].append(nbf.new_worksheet(cells=cells))

with open('my_notebook.ipynb', 'w') as f:
        nbf.write(nb, f, 'ipynb')
于 2014-05-19T04:14:07.017 回答
17

我不会判断这是否是一个好主意,但是如果您get_ipython().set_next_input(s)在笔记本中调用,它将创建一个带有字符串的新单元格s。这就是 IPython 内部用于其%load%recall命令的内容。

于 2012-11-29T17:39:24.547 回答
8

请注意,Tal 接受的答案有点被弃用并且越来越被弃用:在 ipython v3 中,您可以(/应该)nbformat直接导入,之后您需要指定要创建的笔记本版本。

所以,

from IPython.nbformat import current as nbf

变成

from nbformat import current as nbf

变成

from nbformat import v4 as nbf

然而,在这个最终版本中,兼容性中断了,因为该write方法位于父模块nbformat中,而 Fernando Perez 使用的所有其他方法都在该v4模块中,尽管其中一些名称不同(例如new_text_cell('markdown', source)become new_markdown_cell(source))。

是 v3 处理方式的示例:查看generate_examples.py代码和plotstyles.ipynb输出。在撰写本文时,IPython 4 非常新,以至于使用 Web 界面并单击“新笔记本”仍会生成 v3 笔记本。

于 2015-11-05T19:40:32.477 回答
3

下面是函数的代码,它将加载文件的内容并将其插入笔记本的下一个单元格:

from IPython.display import display_javascript

def make_cell(s):
   text = s.replace('\n','\\n').replace("\"", "\\\"").replace("'", "\\'")
   text2 = """var t_cell = IPython.notebook.get_selected_cell()
   t_cell.set_text('{}');
   var t_index = IPython.notebook.get_cells().indexOf(t_cell);
   IPython.notebook.to_code(t_index);
   IPython.notebook.get_cell(t_index).render();""".format(text)
   display_javascript(text2, raw=True)

def insert_file(filename):
   with open(filename, 'r') as content_file:
       content = content_file.read()
   make_cell(content)

在我的博客中查看详细信息。

于 2018-03-30T09:03:23.437 回答
2

使用魔法可能是另一种解决方案。例如

get_ipython().run_cell_magic(u'HTML', u'', u'<font color=red>heffffo</font>')

现在您可以在单元格中以编程方式生成 HTML,您可以根据需要以任何方式进行格式化。当然支持图像。如果您想重复生成多个单元格的输出,只需将字符串作为占位符执行上述多个操作。

ps 我曾经有过这种需求并到达了这个线程。当时我想渲染一个表(不是列表和元组的 ascii 输出)。后来我发现pandas.DataFrame它非常适合我的工作。它会自动生成 HTML 格式的表格。

于 2013-09-12T11:43:19.100 回答
1
from IPython.display import display, Javascript

def add_cell(text,  type='code', direct='above'):
    text = text.replace('\n','\\n').replace("\"", "\\\"").replace("'", "\\'")
    display(Javascript('''
        var cell = IPython.notebook.insert_cell_{}("{}")
        cell.set_text("{}")
        '''.format(direct, type, text)));

for i in range(3):
    add_cell(f'# heading{i}', 'markdown')
    add_cell(f'code {i}')

上面的代码会添加如下单元格: 在此处输入图像描述

于 2021-10-28T08:53:13.240 回答
0

使用命令行转到 myfile.py 文件所在的目录并执行(示例):C:\MyDir\pip install p2j

然后执行:C:\MyDir\p2j myfile.py -t myfile.ipynb

于 2020-04-15T20:53:35.227 回答
0

在 Jupyter 笔记本中运行:

!pip install p2j

然后,使用命令行,进入文件所在的对应目录,执行:

python p2j <myfile.py> -t <myfile.ipynb> 
于 2020-04-15T20:49:34.363 回答
0

@xingpei Pang 解决方案非常完美,特别是如果您想为每个具有多个组的数据集创建自定义代码。但是,javascript 代码的主要问题是,如果您在受信任的笔记本中运行此代码,它会在每次加载笔记本时运行。

我想出的解决方案是在执行后清除单元格输出。javascript 代码存储在输出单元格中,因此通过清除输出,代码就消失了,并且没有任何内容可以再次在受信任模式下执行。通过使用此处的代码,解决方案是下面的代码。

from IPython.display import display, Javascript, clear_output

def add_cell(text,  type='code', direct='above'):
    text = text.replace('\n','\\n').replace("\"", "\\\"").replace("'", "\\'")
    display(Javascript('''
        var cell = IPython.notebook.insert_cell_{}("{}")
        cell.set_text("{}")
        '''.format(direct, type, text)));

# create cells
for i in range(3):
    add_cell(f'# heading{i}', 'markdown')
    add_cell(f'code {i}')
    

# clean the javascript code from the current cell output
for i in range(10):
    clear_output(wait=True)

请注意,clear_output()需要多次运行以确保清除输出。

于 2021-11-22T08:53:17.073 回答
0

作为包含Tal 上述答案的轻微更新,来自 Chris Barnes的更新和对nbformat 文档的一点挖掘,以下内容对我有用:

import nbformat
from nbformat import v4 as nbf

nb = nbf.new_notebook()

cells = [
    nbf.new_code_cell(f"""print("Doing the thing: {i}")""")
    for i in range(10)
]

nb.cells.extend(cells)

with open('generated_notebook.ipynb', 'w') as f:
    nbformat.write(nb, f)

然后,您可以启动新的人工笔记本并在任何需要的地方剪切和粘贴单元格。

这不太可能是做任何事情的最佳方式,但它作为一个肮脏的黑客很有用。‍</p>

这适用于以下版本:

Package              Version
-------------------- ----------
ipykernel            5.3.0
ipython              7.15.0
jupyter              1.0.0
jupyter-client       6.1.3
jupyter-console      6.1.0
jupyter-core         4.6.3
nbconvert            5.6.1
nbformat             5.0.7
notebook             6.0.3
...
于 2020-06-17T19:25:48.873 回答