IPython notebook: How to write cell magic which ca

2019-08-02 11:17发布

问题:

My question is: How can I write an IPython cell magic which has access to the namespace of the IPython notebook?

IPython allows writing user-defined cell magics. My plan is creating a plotting function which can plot one or multiple arbitrary Python expressions (expressions based on Pandas Series objects), whereby each line in the cell string is a separate graph in the chart.

This is the code of the cell magic:

def p(line, cell):
    import pandas as pd
    import matplotlib.pyplot as plt

    df = pd.DataFrame()
    line_list = cell.split('\n')

    counter = 0
    for line in line_list:
        df['series' + str(counter)] = eval(line)      
        counter += 1

    plt.figure(figsize = [20,6])
    ax = plt.subplot(111)
    df.plot(ax = ax)


def load_ipython_extension(ipython):
    ipython.register_magic_function(p, 'cell')

The function receives the entire cell contents as a string. This string is then split by line breaks and evaluated using eval(). The result is added to a Pandas DataFrame. Finally the DataFrame is plotted using matplotlib.

Usage example: First define the Pandas Series object in IPython notebook.

import pandas as pd
ts = pd.Series([1,2,3])

Then call the magic in IPython notebook (whereby the whole code below is one cell):

%%p
ts * 3
ts + 1

This code fails with the following error:

NameError: name 'ts' is not defined

I suspect the problem is that the p function only receives ts * 3\n ts + 1 as a string and that it does not have access to the ts variable defined in the namespace of IPython notebook (because the p function is defined in a separate .py file).

How does my code have to be changed so the cell magic has access to the ts variable defined in the IPython notebook (and therefore does not fail with the NameError)?

回答1:

Use the @needs_local_scope decorator decorator. Documentation is a bit missing, but you can see how it is used, and contributing to docs would be welcome.



回答2:

You could also use shell.user_ns from Magics. For example something like:

from IPython.core.magic import Magics

class MyClass(Magics):
    def myfunc(self):
        print(self.shell.user_ns)

See how it's used in code examples: here and here.