对不起那种一般性问题。关于我想要的更多细节:
我希望用户能够编写一些Python代码并执行它。一旦有未处理的异常,我希望调试器暂停执行,显示有关当前状态/环境/堆栈/异常的信息,并使编辑代码成为可能。
我只希望特殊代码块可以在发生异常的地方编辑,而不是其他任何东西(现在)。即如果它发生在for
循环中,我只想让for
循环内的代码块可编辑。它应该是最新/最新的代码块,它位于用户编辑器范围内(而不是在其他一些库或Python库中)。在这种情况下,始终清楚要编辑的代码块。
我已经尝试过调查一下如何做到这一点,虽然我觉得有点迷失。
Python回溯不直接给我代码块,只是函数和代码行。我可以算一下这个,但这对我来说似乎有些笨拙。如果我能以某种方式获得对代码AST中的代码块的引用,那就更好(也更自然)。
要获取AST(并对其进行操作,即操作/编辑),我可能会使用compiler
(已弃用?)和/或parser
模块。或ast
模块。虽然我不知道如何重新编译AST中的特殊节点/代码块。或者如果我只能重新编译整个函数。
答案 0 :(得分:2)
使用ast
和compile
(内置)似乎您可以使用NodeTransformer
修改某些节点...如果您还可以手动编辑它们知道你在找什么。
test.py
print 'Dumb Guy'
x = 4 + 4
print x * 3
change.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的输出:
酷男郎 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进行此类操作。
答案 1 :(得分:0)
我想知道HAP Remote Debugger for Python对你有用吗?我不认为他们有实时编辑,但是一些调试方面可能仍然有用。
答案 2 :(得分:0)
从我在此期间发现的情况来看,这是不可能的。至少不是块状的。可以按函数重新编译代码,但不能按代码块重新编译代码,因为Python会为每个函数生成代码对象。
所以唯一的方法是编写自己的Python编译器。