python - 如何编写 Python 调试器/编辑器

标签 python compiler-construction parsing stack-trace abstract-syntax-tree

对于这种一般性问题,我们深表歉意。有关我想要的内容的更多详细信息:

我希望用户能够编写一些 Python 代码并执行它。一旦出现未处理的异常,我希望调试器暂停执行,显示有关当前状态/环境/堆栈/异常的信息,并可以编辑代码

我只想让发生异常的特殊代码块可编辑,别无其他(目前)。 IE。如果它发生在 for 循环内,我只想让 for 循环内的代码块可编辑。它应该是用户编辑器范围内的最新/最近的代码块(而不是在其他一些库或 Python 库中)。在这种情况下,编辑什么代码块总是很清楚。


虽然我觉得有点迷茫,但我已经尝试调查了一下如何做到这一点。

Python 回溯不直接给我代码块,只给我函数和代码行。我可以计算回来,但这对我来说似乎有点老套。如果我能以某种方式在代码的 AST 中获得对代码块的引用,那就更好(也更自然)了。

要获取 AST(并对其进行操作,即操作/编辑),我可能会使用编译器(已弃用?)和/或解析器模块。或者 ast 模块。不确定如何在 AST 中重新编译特殊节点/代码块。或者如果我只能重新编译整个函数。

最佳答案

尝试使用 astcompile(内置),您似乎可以使用 NodeTransformer 来修改一些节点。 . 如果您知道要查找的内容,也可以手动编辑它们。

测试.py

print 'Dumb Guy'
x = 4 + 4
print x * 3

改变.py

import ast
with open('test.py') as f:
    expr = f.read()

e = ast.parse(expr)
e.body[0].values[0].s = 'Cool Guy'       # Replace the string
e.body[1].targets[0].id = 'herring'      # Change x to herring
e.body[2].values[0].left.id = 'herring'  # Change reference to x to reference to herring
c = compile(e, '<string>', 'exec')
exec(c)

change.py 的输出:

Cool Guy
24

您也可以通过这种方式向正文添加代码(或以替换列表元素的通常方式替换元素):

p = ast.parse('print "Sweet!"', mode='single')
e.body.extend(p)

然后重新编译并执行:

c = compile(e, '<string>', 'exec')
exec(c)

您可以用这种方式替换函数定义或单行。一个函数定义会有它自己的主体,所以如果你添加了一些函数(或循环),你可以访问它

e.body[N].body  # Replace N with the index of the FunctionDef object

但是,据我所知执行单个 ast 对象(_ast.Print_ast.Assign 或其他)的唯一方法是执行如下操作:

e2 = ast.parse('', mode='exec')
e2.body.append(e.body[0])
exec(compile(e2, '<string>', 'exec'))

这对我来说似乎有点骇人听闻。就行而言 - AST 中的每个对象都有一个 lineno 属性,因此如果您可以从异常中检索行号,您可以很容易地找出哪个语句引发了异常。

当然,这并不能真正解决将堆栈倒回异常前状态的问题,这听起来像是您真正想要做的。但是,可以通过 pdb 来做这样的事情。 .

关于python - 如何编写 Python 调试器/编辑器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3229102/

相关文章:

c++ - 使用 boost::spirit 解析 Newick 语法

regex - 如何使用 R 解析 sysmon 文件以提取某些信息?

python - ConfigParser 不支持的操作数类型

python - 默认或以编程方式对 TreeView 中的列进行排序

Python/Pandas 逐行写入文件::内存使用

python - 如何使相等数字参数出现的键值

python - numpy cumsum 函数的反函数是什么?

c++ - 编译器编程 : What are the most fundamental ingredients?

compiler-construction - Haskell - 如何最好地表示编程语言的语法?

C 编译器断言 : how to dynamically use them wherever the expression is fixed?