逐步跟踪Python表达式评估

Ily*_*rov 11 python abstract-syntax-tree

我正在尝试编写Python表达式评估可视化工具,它将显示如何逐步评估Python表达式(用于教育目的).Philip Guo的Python Tutor很棒,但它逐行评估Python程序,我发现学生有时不理解单行表达式sorted([4, 2, 3, 1] + [5, 6])[1] == 2是如何评估的,我想要想象这个过程.(似乎没有人做过 - 至少我什么也没发现.)理想的解决方案是创建一系列字符串,如下所示:

sorted([4, 2, 3, 1] + [5, 6])[1] == 2
sorted( >> [4, 2, 3, 1] + [5, 6] << )[1] == 2
>> sorted([4, 2, 3, 1, 5, 6]) << [1] == 2
>> [1 2 3 4 5 6][1] << == 2
>> 2 == 2 <<
True
Run Code Online (Sandbox Code Playgroud)

这里>><<用来突出显示对当前步骤评估,然后通过它的值替换表达式的一部分.(也许,我会尝试将此序列转换为某种动画.)

我当前的策略是使用ast.parse()将字符串解析为AST,然后找到一个将首先评估的节点,用它评估它eval(compile(node, '', 'eval'))(我绝对不想重新实现整个Python :)),将评估结果转换为AST节点(有repr,然后ast.parse()?)并用结果节点替换当前节点,然后用来codegen.to_source从(修改的)AST生成修改的代码字符串并继续相同的过程,直到我在树中只有一个文字.

我的问题是:如何找到首先评估的节点?似乎我可以通过子类化遍历树深度 - ast.NodeVisitor但是我不确定如何检测到我到达了所需的节点以及如何在它之后停止遍历?


编辑.

我对树的转换的初始方法可能是不可行的.事实上,评估Python表达式的基本步骤不是必须将某个子表达式替换为更简单的表达式(如算术中).例如,列表推导提供了一个更复杂的行为,无法用术语替换这个东西,然后递归重复.所以我稍微重申了一个问题.我需要一些方法来programmaticaly显示如何逐步评估Python表达式.例如,@ jasonharper 提到的MacroPy的跟踪功能在此阶段是可接受的解决方案.不幸的是,MacroPy似乎被放弃了,并且不适用于Python 3.在没有移植完整的MacroPy的情况下,有没有想法如何在Python 3中类似这种跟踪行为?


EDIT2.

在我获得此奖金之后,我发现了类似的问题和一个具有非常接近功能的调试器.但是,由于这个问题没有最终答案,而且我不需要完整的调试器,我仍然在寻找可以在Jupyter环境中使用的答案.

Aiv*_*var 5

表达式步进在Thonny IDE中实现.

它使用AST检测,其中每个(子)表达式e被转换为 after(before(<location info>), e).函数beforeafter虚函数,用于在Python的跟踪系统中引起额外的调用事件.当(子)表达式评估即将开始或刚刚结束时,这些额外调用会通知.(添加类似的虚函数来检测每个语句的开始和结束.)

这些新事件的AST检测和解释在thonny.backend.FancyTracer中完成.

Python的AST节点包含相应文本范围的起始位置,但它们有时不正确.结束位置完全缺失.thonny.ast_utils.mark_text_ranges试图解决这个问题(但目前解决方案尚未完成).

如果有人从Thonny中提取相关功能到一个更通用的包,那将是很好的.甚至可能是两个包 - 一个用于计算Python AST的位置信息,另一个用于详细跟踪Python代码.如果有人带头,我愿意帮忙.