CPython解释器如何知晓要打印最后一个表达式的结果?
探究CPython交互模式中表达式结果的打印时机
我最近一直在研究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编译为字节码,随后在虚拟机中执行字节码并得到结果。而且PyRun_InteractiveOneObjectEx()返回的Python对象,正是虚拟机栈的栈顶元素。
这部分逻辑都符合我的预期,但紧接着我发现这个返回值好像被丢弃了!那问题来了——REPL到底是在什么时候打印这个表达式结果的呢?
另外我还注意到一个细节:交互模式会修改分词器,它会使用sys.ps1提示符(默认值是">>> ")调用PyOS_Readline。我特意检查了pythonrun.c里的相关代码,但没找到和打印结果相关的修改逻辑。
内容的提问来源于stack exchange,提问作者chrisaycock
相关产品推荐
相关产品推荐

