打印Jupyter单元格中定义的所有变量

7

有没有更简单的方法以漂亮的方式显示单个单元格中定义的所有变量的名称和值?

我现在的做法是这样的,但当有30个或更多变量时,我浪费了很多时间:

enter image description here


3
请发布您的代码,而不是图片文件。 - Joe T. Boka
3个回答

7
你可以使用 whos 命令查看当前内核中存储的 所有 变量。
k, g, lx = .4, .8, 6.6
m = k*g*lx**2
whos

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

但是,正如所说的,它显示所有变量,因此它将显示您运行过的早期单元格中的其他变量。

可以使用Python内置函数locals()globals()命令来实现类似的结果,它们返回一个变量字典。但是Jupyter的表示方式更加美观。


或者您可以使用交互式Shell。这将改变单元格的行为,并像Python shell一样运行,因此一旦运行,它将输出每个调用的值(到输出单元格)。

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

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

输出:

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

最后,您可以通过将其设置为last_expr来将交互性恢复为默认值。

InteractiveShell.ast_node_interactivity = "last_expr"

但是你做这件事的方式可能是最简单和最漂亮的方式,你可以只需删除dataframe上的赋值语句,使其成为一行代码,或者可以更紧凑地调用它:
k, g, lx, m

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

1
感谢您提供详细的答案! - Yuri F Becker

6

所以,这是一个难题。基本上,我们只是试图抓住当前单元格中的所有行并提取变量。事实证明,我们不能使用IPython定义的全局变量(例如____i<n>等)如Programmatically get current Ipython notebook cell output?建议的那样,因为(据我所做的实验所示),您只能从先前执行的单元格中获取值,而不能从当前执行的单元格中获取。

幸运的是,结果发现使用魔术命令%history确实可以获取当前单元格的输入。所以,借助这个链接这个链接,我创建了一个函数,正好可以满足您的需求:

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

您可以通过以下方式进行测试:

a = 1
b = 2
c = 3

cell_vars()

代码应该会产生{'a': 1, 'b': 2, 'c': 3},然后您可以根据自己的喜好进行格式化和打印。显然,我的行处理存在一些限制(假设所有感兴趣的变量都在全局范围内)。

希望这对您有用!


这正是我项目所需的,谢谢!您的代码在IPython 8.1中会出现弃用警告,但这可以通过将ipy.magic....替换为ipy.run_line_magic("history", format(ipy.execution_count - offset))来非常简单地解决。 - wjmatthews
抱歉没有格式化代码。更新的解决方案是 ipy.run_line_magic("history", format(ipy.execution_count - offset) - wjmatthews

2
你可以尝试使用inspect库来实现类似以下的功能: inspect
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

谢谢,但我遇到了一个错误。我复制并粘贴了完全相同的代码,但它显示:“传递的值的形状为(30,2),而索引则意味着(30,1)”。 - Yuri F Becker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接