使用 pythonspect 查看函数中的局部变量
我不知道如何使用 inspect / inspect_shell
我猜它涉及使用 getinnerframe 和 getouterframe 遍历框架层次结构,但我对几个问题感到困惑。
鉴于这个例子 nine.py:
import inspect_shell
import time
def number_nine():
x = 9
while x==9:
time.sleep(1)
number_nine()
print x
我想检查 x 的值,甚至可能更改它以使函数返回并打印新值。
首先,我启动 nine.py,然后在单独的命令窗口中,使用 inspect_shell,我看到 < code>getinnerframes 不适用于当前帧(它需要跟踪(也许?))并且当前帧没有“跟踪”。和 getouterframes (如果我向后思考这个问题)似乎只得到与我的功能无关的帧。
>> Inspect Shell v1.0
>> https://github.com/amoffat/Inspect-Shell
localhost:1234> import inspect
localhost:1234> f = inspect.currentframe()
localhost:1234> inspect.getinnerframes(f)
Traceback (most recent call last):
File "C:\Users\Paul\Desktop\inspect_shell.py", line 143, in run_repl
try: exec compile(data, "<dummy>", "single") in f_globals, f_globals
File "<dummy>", line 1, in <module>
File "C:\Python26\lib\inspect.py", line 942, in getinnerframes
framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
AttributeError: 'frame' object has no attribute 'tb_frame'
localhost:1234> dir(f)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'f_back', 'f_builtins',
'f_code', 'f_exc_traceback', 'f_exc_type', 'f_exc_value', 'f_glo
bals', 'f_lasti', 'f_lineno', 'f_locals', 'f_restricted', 'f_trace']
localhost:1234> print f.f_trace
None
localhost:1234> inspect.getouterframes(f)
[(<frame object at 0x0237D470>, '<dummy>', 1, '<module>', None, None),
(<frame object at 0x02375938>, 'C:\\Users\\Paul\\Desktop\\inspect_shell.py', 14
3, 'run_repl', [' try: exec compile(data, "<dummy>", "single") in
f_globals, f_globals\n'], 0), (<frame object at 0x023A2C30>, 'C:\
\Python26\\lib\\threading.py', 484, 'run',
[' self.__target(*self.__args, **self.__kwargs)\n'], 0),
(<frame object at 0x02397F28>, 'C:\
\Python26\\lib\\threading.py', 532, '__bootstrap_inner',
[' self.run()\n'], 0), (<frame object at 0x023A9D68>,
'C:\\Python26\\lib\\thre
ading.py', 504, '__bootstrap', [' self.__bootstrap_inner()\n'], 0)]
I can't figure out how to inspect a currently executing function using inspect / inspect_shell
I'm guessing it involves walking the frame hierarchy using getinnerframe and getouterframe, but I'm confused on several issues.
Given this example
nine.py:
import inspect_shell
import time
def number_nine():
x = 9
while x==9:
time.sleep(1)
number_nine()
print x
I would like to inspect the value of x
or even possibly change it to cause the function to return and print the new value.
First I launch nine.py, then in a separate command window, using inspect_shell, I see that getinnerframes
does not work on the current frame (it needs a trace (perhaps?)) and the current frame has no "trace". and getouterframes
(in case I'm thinking about this backwards) seems to get only frames that have nothing to do with my function.
>> Inspect Shell v1.0
>> https://github.com/amoffat/Inspect-Shell
localhost:1234> import inspect
localhost:1234> f = inspect.currentframe()
localhost:1234> inspect.getinnerframes(f)
Traceback (most recent call last):
File "C:\Users\Paul\Desktop\inspect_shell.py", line 143, in run_repl
try: exec compile(data, "<dummy>", "single") in f_globals, f_globals
File "<dummy>", line 1, in <module>
File "C:\Python26\lib\inspect.py", line 942, in getinnerframes
framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
AttributeError: 'frame' object has no attribute 'tb_frame'
localhost:1234> dir(f)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'f_back', 'f_builtins',
'f_code', 'f_exc_traceback', 'f_exc_type', 'f_exc_value', 'f_glo
bals', 'f_lasti', 'f_lineno', 'f_locals', 'f_restricted', 'f_trace']
localhost:1234> print f.f_trace
None
localhost:1234> inspect.getouterframes(f)
[(<frame object at 0x0237D470>, '<dummy>', 1, '<module>', None, None),
(<frame object at 0x02375938>, 'C:\\Users\\Paul\\Desktop\\inspect_shell.py', 14
3, 'run_repl', [' try: exec compile(data, "<dummy>", "single") in
f_globals, f_globals\n'], 0), (<frame object at 0x023A2C30>, 'C:\
\Python26\\lib\\threading.py', 484, 'run',
[' self.__target(*self.__args, **self.__kwargs)\n'], 0),
(<frame object at 0x02397F28>, 'C:\
\Python26\\lib\\threading.py', 532, '__bootstrap_inner',
[' self.run()\n'], 0), (<frame object at 0x023A9D68>,
'C:\\Python26\\lib\\thre
ading.py', 504, '__bootstrap', [' self.__bootstrap_inner()\n'], 0)]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这有点棘手,但是给定源代码(或一个好的Python反编译器),你可以这样做:
在'nine.py'中:
你的邪恶代码:
我们需要使用ast,即抽象语法树:
现在我们获取源代码并将其转换为 ast:
隔离要更改的特定语句:
并且改变它如您所见:
现在剩下要做的就是将修改后的 ast 对象编译为更有用的东西:
您可以使用简单的
exec
(如果它在中,它将替换 'number_nine' globals
),或exec in
,并将其放入临时模块中:然后砰!它打印
x: It's a trap!
This is kind of tricky, but given the source code (or a good python decompiler), you can do this:
in 'nine.py':
Your evil code:
We need to use ast, which is Abstract Syntax Trees:
Now we get the source and transform it to an ast:
Isolate the specific statement you want to change:
And alter it as you see fit:
Now all that is left to do is to compile your modified ast object to something more useful:
You can use simple
exec
(which will replace 'number_nine' if it is inglobals
), orexec in
, and place it in a temp module:And bang! it prints
x: It's a trap!
Inspect Shell 的作者在这里 :) 您可能需要使 x 可从全局命名空间访问。 Inspect Shell 本质上会将您带入正在运行的脚本的全局命名空间,因此如果无法从那里访问某些数据,那么访问它将会非常困难。
所以真正的建议是,使 x 全局化,然后您应该能够更改它并且您的 number_nine() 函数将返回。
希望有帮助!
Author of Inspect Shell here :) You're probably going to need to make x accessible from the global namespace. Inspect Shell essentially drops you into the global namespace of the running script, so if some data can't be reached from there, it's going to be really tricky to get to it.
So really the suggestion is, make x global, then you should be able to alter it and your number_nine() function will return.
Hope that helps!