Yuri F Becker
Yuri F Becker

Reputation: 368

Print all variables defined in one Jupyter cell

Is there an easier way to display the name and the value of all variables defined in a single cell in a pretty way?

The way I'm doing now is like this, but I waste a lot of time when there are 30 variables or more:

enter image description here

Upvotes: 7

Views: 9565

Answers (3)

BenedictWilkins
BenedictWilkins

Reputation: 1263

So, this was a tough nut to crack. Essentially we are just trying to grab all of the lines in the current cell and extract the variables. As it turns out, we cannot use the global variables defined by IPython (e.g. _, __, _i<n> etc) as suggested in Programmatically get current Ipython notebook cell output? because (as far as my experiments have shown) you can only grab values from previously executed cells and not the one currently being executed.

Luckily for us, it turns out that using the magic command %history does grab the input of the current cell. So with the help of this and this I have created a function that does exactly what you want:

def cell_vars(offset=0):
    import io
    from contextlib import redirect_stdout

    ipy = get_ipython()
    out = io.StringIO()

    with redirect_stdout(out):
        ipy.magic("history {0}".format(ipy.execution_count - offset))

    #process each line...
    x = out.getvalue().replace(" ", "").split("\n")
    x = [a.split("=")[0] for a in x if "=" in a] #all of the variables in the cell
    g = globals()
    result = {k:g[k] for k in x if k in g}
    return result

You can test it with something like:

a = 1
b = 2
c = 3

cell_vars()

which should give {'a': 1, 'b': 2, 'c': 3}, you can then format this and print it however you like. Obviously there are some limitations with my line processing (assumes that all variables of interest are in global scope).

Hope this is useful!

Upvotes: 6

umutto
umutto

Reputation: 7690

You can use whos command to see all variables stored in the current kernel.

k, g, lx = .4, .8, 6.6
m = k*g*lx**2
whos

outputs:

Variable   Type     Data/Info
-----------------------------
g          float    0.8
k          float    0.4
lx         float    6.6
m          float    13.939200000000001

But as said, it displays all variables, so it will display other variables from earlier cells you've run.

A similar result can be achieved using locals() or globals() command from python built-in functions, which return a dictionary of variables. But the way jupyter represents is prettier.


Alternatively you can use InteractiveShell. This will change the behavior of cells and act like a python shell would, so it will output every called value (to output cell) once run.

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

k
g
... do stuff ...
lx
m
... do more stuff ...

outputs:

Out[2]: 0.4
Out[2]: 0.8
Out[2]: 6.6
Out[2]: 13.939200000000001

And finally you can return the interactivity to default by setting it to last_expr.

InteractiveShell.ast_node_interactivity = "last_expr"

But the way you do it is probably the easiest and prettiest way, you can just remove the assignment on dataframe to make it a one liner or you can make it more compact to call by:

k, g, lx, m

Out[3]: (0.4, 0.8, 6.6, 13.939200000000001)

Upvotes: 7

Joe T. Boka
Joe T. Boka

Reputation: 6581

You can try something like this, using the inspect library.

import inspect

k = 0.0417
g = 0.829
lx = 6.6
m = k*g*lx**2

def get_name(lst=[]):
    local_vars = inspect.currentframe().f_back.f_locals.items()
    for i in local_vars:
        lst.append(i)
    return dict(lst)

import pandas as pd

df = pd.DataFrame(get_name(), index=[0])
result = df.T.loc[df.dtypes != object]
print(result)
          0
g     0.829
k     0.0417
lx    6.6
m     1.50584

Upvotes: 2

Related Questions