首页 > 解决方案 > CPython 的解释器如何知道打印最后一个表达式的结果?

问题描述

我一直在挖掘源代码以找出打印结果的时间点。例如:

>>> x = 1
>>> x + 2
3

以上两条语句编译为:

  1           0 LOAD_CONST               0 (1)
              3 STORE_NAME               0 (x)
              6 LOAD_CONST               1 (None)
              9 RETURN_VALUE

  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (2)
              6 BINARY_ADD
              7 RETURN_VALUE

第一条语句不打印任何内容,因为None它是返回值。第二个返回加法的结果。

CPython 的交互式循环调用PyRun_InteractiveOneObjectEx()每个输入。这将获取 AST并调用run_mod()将该 AST 编译为字节码,然后在虚拟机中评估结果。获取的返回 Python 对象PyRun_InteractiveOneObjectEx()只是VM 堆栈的顶部

到目前为止,这一切都是我所期望的。但是随后返回的值似乎被丢弃了!REPL 什么时候打印出来的?

顺便说一句,我可以看到交互模式确实改变了标记器;它invokes PyOS_Readline带有sys.ps1提示(">>> "默认情况下)。我检查了类似的变化pythonrun.c,但没有运气。

标签: pythoncpythonpython-internals

解决方案


您正在显示通过将代码包含在函数中而生成的字节码的反汇编。这不是交互式代码的编译方式:它使用特殊的“单一”模式(compile()如果您在 Python 代码中执行等效操作,则为 的第三个参数)。在这种模式下,POP_TOP丢弃每个表达式的值的操作码会变成 a PRINT_EXPR。什么都不打印的原因x = 1是语句在堆栈上没有留下任何需要弹出的东西,所以这种转换不适用。


推荐阅读