Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jupyter: Write a custom magic that modifies the contents of the cell it's in

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')

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

[Edit]:

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

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?

like image 373
JeremyKun Avatar asked Jun 24 '16 19:06

JeremyKun


People also ask

How do you edit a markdown cell in Jupyter Notebook?

Just double click on the markdown cell. Edit what you want to and Run. It will reflect the changes.

What does %% do in Jupyter Notebook?

Both ! and % allow you to run shell commands from a Jupyter notebook. % is provided by the IPython kernel and allows you to run "magic commands", many of which include well-known shell commands. ! , provided by Jupyter, allows shell commands to be run within cells.

How do I change the text in Jupyter?

The new Find and Replace dialog is found under the Edit menu of the notebook. If you're in command mode, you can press the F key to bring up the dialog. The dialog displays a live preview of the find and replace action you specify.

How do you use %% Timeit in Jupyter?

The “%timeit” is a line magic command in which the code consists of a single line or should be written in the same line for measuring the execution time. In the “%timeit” command, the particular code is specified after the “%timeit” is separated by a space.

What is cell magic in Jupyter Notebook?

In this chapter, let us understand cell magic functions and their functionalities. This cell magic function renders contents of code cell as html script. You can embed javascript code in Jupyter notebook cell with the help of this cell magic command. Contents of code cell are written to a file using this command.

What are magic commands in Jupyter Notebook?

Line Magic Commands: It applies the command to one line of the Jupyter cell as its name suggests. Cell Magic Commands: It applies the command to the whole cell of the notebook and needs to be kept at the beginning of the cell. We'll now explain the usage of magic commands one by one with simple examples.

What are Jupyter magics and how do they work?

Jupyter magics allow us to run convenient utility functions within Jupyter notebooks. Anyone who has done much data analysis in a Jupyter notebook is likely familiar with which causes our matplotlib figures to be rendered in the notebook.

How to embed JavaScript code in Jupyter Notebook cell?

This cell magic function renders contents of code cell as html script. You can embed javascript code in Jupyter notebook cell with the help of this cell magic command. Contents of code cell are written to a file using this command.


Video Answer


1 Answers

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

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.

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.

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)

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.

like image 112
Peter Brittain Avatar answered Sep 20 '22 14:09

Peter Brittain