【问题标题】:Emulate Python shell's "return value" behaviour模拟 Python shell 的“返回值”行为
【发布时间】:2020-05-25 19:04:04
【问题描述】:

假设我有一个要评估的 Python 字符串的 JSON 列表。例如,也许我正在构建一个客户端-服务器 Python GUI。

常规 Python 解释器的一个方便之处在于它显示了每一行的“伪返回值”,如下所示:

 $ python3 -c "import code; code.interact()"
 Python 3.7.7 (default, Mar 10 2020, 15:43:03) 
 (InteractiveConsole)
 >>> import os; os.curdir
 '.'

我不必要求打印出“.”。它就是这么做的。

在幕后,可以看到这是使用 exec() 函数实现的:

https://github.com/python/cpython/blob/800a35c623bbcdb5793c7d7a4974524286311479/Lib/code.py#L90

    try:
        exec(code, self.locals)
    except SystemExit:
        raise
    except:
        self.showtraceback()

奇怪的是那里没有明确的指令来输出 exec() 的结果。然而我们可以看到它确实输出了它。

我们可以看到这种行为是非常特定于上下文的,如下所示:

$ echo "5" | python3 -c "import code; code.interact()"
Python 3.7.7 (default, Mar 10 2020, 15:43:03) 
(InteractiveConsole)
>>> 5
>>> 
now exiting InteractiveConsole...
enter code here

我假设如果我深入研究 C 代码,我会看到它正在查询其上下文以查看是否输出值。但它不会回答我的主要问题,即如何在任意上下文中模拟这种行为。

如何从 Python 字符串中执行并获取“伪返回值”,无论该字符串表示表达式还是语句?

【问题讨论】:

  • code 模块(或其源代码)中可能有一些有用的东西。

标签: python compilation exec eval read-eval-print-loop


【解决方案1】:

Python 编译器有一个flag to keep track of whether Python is being run in interactive mode

如果设置了这个标志,当编译器访问AST中的一个语句节点时,它会emits an extra PRINT_EXPR opcode

解释器executes PRINT_EXPR 将表达式的结果从堆栈中弹出并将其作为参数传递给sys.displayhook。显示挂钩将此值的repr 打印到标准输出,除非该值为无。它还将值分配给builtins._

(我猜当您将命令传递给 Python 时行为不同的原因是它不在交互模式下。)

所以只要你在交互模式下运行 Python,你就可以在使用 exec 内建函数运行代码后读取 _ 内建函数的值。

【讨论】:

  • 我给了你复选标记,因为你接近回答我的整个问题。我的主要问题是“如何在任意上下文中模拟这种行为”,我现在可以根据您对“我可以伪造交互模式吗?”的回答重新表述。我想我可能无法重写 AST 以添加 PRINT_EXPR 并破解我自己的显示钩子。
猜你喜欢
  • 2021-12-02
  • 2015-09-09
  • 1970-01-01
  • 2020-04-06
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多