Search code examples
pythonparsingjupyter-notebookipythonipython-magic

iPython custom cell magic - store output in variable?


I recently discovered iPython magic functions and wrote some custom magic. I would like to use cell magic to parse strings, change them slightly and return the result. Is there a way to store the output of my custom cell magic function in a variable?

I know you can store the output of a line magic function like this:

@register_line_magic
def linemagic(line, cell=None):
    #do something
    return line

hello = %linemagic hello
print(hello)

Which returns:

>>> hello

In case I have larger strings, I would like to use cell magic instead:

@register_cell_magic
def cellmagic(line, cell=None):
    #do something
    return cell

It's not possible to use hello = %%cellmagic ... to store the result. Is there another way to capture the function output?


Solution

  • You can use IPython's input/output caching system:

    Output caching:

    • _ (a single underscore): stores previous output, like Python’s default interpreter.
    • __ (two underscores): next previous.
    • ___ (three underscores): next-next previous.
    • _n (n being the prompt counter): the result of output
    • actually, _4, Out[4] or _oh[4] all do the same thing

    Similarly, for Input caching:

    • _i, _ii, _iii: store previous, next previous and next-next previous inputs.
    • _i4, _ih[4] and In[4]: the content of input <n> (e.g 4)
    In [2]: from IPython.core.magic import register_cell_magic
    
    In [3]: @register_cell_magic
       ...: def cellmagic(line, cell=None):
       ...:     #do something
       ...:     return cell
       ...:
    
    In [4]: %%cellmagic
       ...: "line0"
       ...: "line1"
       ...: "line2"
       ...:
       ...:
    Out[4]: '"line0"\n"line1"\n"line2"\n\n'
    
    In [5]: _
    Out[5]: '"line0"\n"line1"\n"line2"\n\n'
    
    In [6]: _4
    Out[6]: '"line0"\n"line1"\n"line2"\n\n'
    
    In [8]: _i4
    Out[8]: '%%cellmagic\n"line0"\n"line1"\n"line2"'
    
    In [9]: var = _4
    
    In [10]: var
    Out[10]: '"line0"\n"line1"\n"line2"\n\n'