跳转到主要内容

获取当前帧正在执行的AST节点以及其他信息

项目描述

executing

Build Status Coverage Status Supports Python versions 3.5+, including PyPy

这个小包让您能够获取有关帧当前正在执行的信息,特别是正在执行的AST节点。

用法

获取AST节点

import executing

node = executing.Source.executing(frame).node

在这种情况下,node将是一个来自ast标准库模块的AST节点,或者如果节点无法识别(这可能会经常发生,因此应该始终进行检查),则为None。

对于多次调用,如果执行点相同,则node将始终是相同的实例。

如果您有一个跟踪对象,请直接将其传递给Source.executing(),而不是传递tb_frame属性,以获取正确的节点。

获取节点的源代码

为此,您需要单独安装asttokens库,然后获取一个ASTTokens对象

executing.Source.executing(frame).source.asttokens()

executing.Source.for_frame(frame).asttokens()

或使用其中一个便利方法

executing.Source.executing(frame).text()
executing.Source.executing(frame).text_range()

获取当前函数的__qualname__

executing.Source.executing(frame).code_qualname()

executing.Source.for_frame(frame).code_qualname(frame.f_code)

Source类

所有内容都通过Source类进行。每个文件名只创建一个类的实例。建议在创建时或添加方法时对该类进行子类化。像executing这样的类方法会尊重这一点。请参阅源代码和docstrings以获取更多详细信息。

安装

pip install executing

如果您不喜欢这样做,可以简单地复制文件executing.py,没有依赖关系(但当然您不会收到更新)。

它是如何工作的?

假设框架正在执行此行

self.foo(bar.x)

特别是它目前正在获取属性self.foo。查看字节码,特别是frame.f_code.co_code[frame.f_lasti],我们可以知道它正在加载一个属性,但不确定是哪一个。我们可以使用frame.f_lineno来缩小正在执行的语句,并找到表示self.foobar.x的两个ast.Attribute节点。我们如何在不重新创建整个Python编译器的情况下找出它是哪一个呢?

诀窍是略微修改每个候选表达式的AST,并观察字节码指令的变化。我们将AST修改为以下内容

(self.foo ** 'longuniqueconstant')(bar.x)

并编译它,字节码将几乎相同,但会有两个新的指令

LOAD_CONST 'longuniqueconstant'
BINARY_POWER

在这之前将有一个对应于self.fooLOAD_ATTR指令。看到它在原始指令相同的位置,我们知道我们已经找到了匹配项。

它可靠吗?

是的——如果它识别了一个节点,您可以相信它已经识别了正确的节点。测试非常彻底——除了直接检查各种情况的单元测试外,还有针对大量文件(请参阅此构建中打印的文件名)的属性测试,其中包含真实代码。具体来说,对于每个文件,测试

  1. 尽可能从文件中的所有字节码指令中识别出尽可能多的节点,并断言它们都是唯一的
  2. 找到所有应该可识别的节点,并断言它们确实在某个地方被识别

换句话说,它表明节点和可以处理的指令之间存在一对一的映射。这留给错误的余地很小。

此外,executing检查从修改后的AST编译的指令与原始代码(除了一些已知的小异常外)完全匹配。这解释了解释器中的所有怪癖和优化。

它可以识别哪些节点?

目前它适用于以下ast节点的几乎所有情况

  • Call,例如self.foo(bar)
  • Attribute,例如point.x
  • Subscript,例如lst[1]
  • BinOp,例如x + y(不包括andor
  • UnaryOp,例如-n(包括not但有时不起作用)
  • Compare,例如a < b(不适用于链,如0 < p < 1

计划在未来扩展到更多操作。

使用此技术的项目

我的项目

  • stack_data:从堆栈帧和回溯中提取数据,特别是显示比默认更有用的回溯。还使用我的另一个相关库:pure_eval
  • futurecoder:通过stack_data使用executing突出显示回溯中的执行节点,并使用snoop提供调试。
  • snoop:一个功能丰富且方便的调试库。使用executing显示导致异常的操作,并允许pp函数显示其参数的源代码。
  • heartrate:Python程序执行过程的简单实时可视化。使用executing突出显示当前正在执行的操作,尤其是在堆栈跟踪的每一帧中。
  • sorcery:Python中的暗黑魔法乐趣。使用executing让特殊的可调用对象(魔法)知道它们被调用的位置。

我贡献的项目

  • IPython:使用stack_data通过executing突出显示跟踪回溯中的执行节点。
  • icecream:🍦 甜美香浓的打印调试。使用executing识别ic被调用的位置并打印其参数。
  • friendly_traceback:使用stack_dataexecuting定位错误原因并提供有用的说明。
  • python-devtools:使用executing进行类似于icecream的打印调试。
  • sentry_sdk:将集成sentry_sdk.integrations.executingExecutingIntegration()添加到sentry事件中显示每个帧的__qualname__函数。
  • varname:关于Python中变量名称的暗黑魔法。使用executing查找其各种魔法函数(如varnamenameof)的调用位置。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

executing-2.1.0.tar.gz (977.5 kB 查看散列)

上传时间

构建分布

executing-2.1.0-py2.py3-none-any.whl (25.8 kB 查看散列)

上传时间 Python 2 Python 3

支持