本文介绍了Jupyter:编写定制魔术来修改其所在单元格的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Jupyter笔记本中,有一些内置的魔术可以改变笔记本单元的内容.例如,%load魔术将当前单元格的内容替换为文件系统上文件的内容.

In a Jupyter notebook there are some built-in magics that change the contents of a notebook cell. For example, the %load magic replaces the contents of the current cell with the contents of a file on the file system.

如何编写类似功能的自定义魔术命令?

How can I write a custom magic command that does something similar?

到目前为止,我所拥有的内容可以打印出一些标准内容

What I have so far prints something to stdout

def tutorial_asset(line):
    print('hello world')


def load_ipython_extension(ipython):
    ipython.register_magic_function(tutorial_asset, 'line')

我可以用%load_ext tutorial_asset加载它.但是从那里我迷路了.

And I can load it with %load_ext tutorial_asset. But from there I'm lost.

:

我找到了一种进入交互式shell实例的方法:

I've found a way to get to the interactive shell instance:

  @magics_class
  class MyMagics(Magics):

      @line_magic
      def tutorial_asset(self, parameters):
          self.shell

self.shell对象似乎可以完全访问笔记本中的单元格集,但是我发现修改单元格的唯一方法是执行self.shell.set_next_input('print("hello world")').这还不够,因为在Jupyter笔记本中,该输入单元格被跳过,并且不覆盖输入单元格,而是在其后创建了一个新的输入单元格.

The self.shell object seems to give complete access to the set of cells in the notebook, but the only way I can find to modify the cells is to do self.shell.set_next_input('print("hello world")'). This isn't sufficient because, in a Jupyter notebook, that input cell is skipped, and it doesn't overwrite the input cell, it instead creates a new input cell after it.

这很好,但是如果我第二次运行笔记本,它会创建另一个加载了相同文件的输入单元,这很烦人.通过检查内容是否已经在下一个单元格中,我是否只能加载一次?

This would be fine, but if I run the notebook a second time, it creates another input cell with the same file loaded, which is annoying. Can I have it load only once, say, by checking if the contents are already in the next cell?

推荐答案

EDIT :经过进一步的挖掘,我发现当前的笔记本不能同时实现这两种功能.

EDIT: After a little further digging, I found that the current build of notebook cannot do both.

好吧,这有点棘手...看一下IPython代码,如果要替换单元格,似乎需要使用set_next_input,而实际上要运行一些代码,则需要使用run_cell.但是,我不能同时使两者同时工作-看来set_next_input总是赢.

Well, this is a little tricky... Looking at the IPython code, it looks like you need to use set_next_input if you want to replace the cell, and run_cell if you actually want to run some code. However, I can't get both to work at once - it looks like set_next_input always wins.

深入到代码中,Web前端支持set_next_input上可选清除输出.但是,内核尚不支持设置此标志(因此输出将始终被清除为默认操作).为了做得更好,需要对ipykernel进行补丁.

Digging into the code, the web front-end supports optional clearing of the output on set_next_input. However, the kernel doesn't yet support setting this flag (and so output will always be cleared as the default action). To do better will require a patch to ipykernel.

因此,我拥有的最好的是使用jupyter Notebook版本4.2.1的以下代码:

The best I therefore have is the following code, using jupyter notebook version 4.2.1:

from __future__ import print_function
from IPython.core.magic import Magics, magics_class, line_magic

@magics_class
class MyMagics(Magics):

    @line_magic
    def lmagic(self, line):
        "Replace current line with new output"
        raw_code = 'print("Hello world!")'
        # Comment out this line if you actually want to run the code.
        self.shell.set_next_input('# %lmagic\n{}'.format(raw_code), replace=True)
        # Uncomment this line if you want to run the code instead.
        # self.shell.run_cell(raw_code, store_history=False)

ip = get_ipython()
ip.register_magics(MyMagics)

这为您提供了一个神奇的命令lmagic,该命令将替换当前单元格或运行raw_code,具体取决于您注释掉的代码的哪一部分.

This gives you a magic command lmagic that will either replace the current cell or run the raw_code depending on which bit of the code you have commented out.

这篇关于Jupyter:编写定制魔术来修改其所在单元格的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 19:23
查看更多