python - 使用 python inspect 查看函数中的局部变量

标签 python inspect code-inspection

我不知道如何使用 inspect 检查当前正在执行的函数/inspect_shell

我猜它涉及使用 getinnerframe 和 getouterframe 遍历框架层次结构,但我对几个问题感到困惑。

给定这个例子 九.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 ,我看到 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)]

最佳答案

这有点棘手,但鉴于源代码(或一个好的 python 反编译器),您可以这样做:

在'nine.py'中:

def number_nine():
    x = 9
    if x == 9:
        print 'x is Nine!'
    else:
        print 'x:', x

你的恶意代码:

from nine import number_nine

我们需要用到ast,即Abstract Syntax Trees :

import inspect
import ast

现在我们获取源并将其转换为 ast:

# Assuming you have the source, we can generate AST from it
nine_src = inspect.getsource(number_nine)
nine_ast = ast.parse(nine_src)

隔离要更改的特定语句:

# This is the Assign object, which represents the 'x = 9' line
# Try to run it interactivly and see how it looks...
x_assign = nine_ast.body[0].body[0]

# Prints 'x'
print x_assign.targets[0].id
# Prints 9
print x_assign.value.n

并根据需要修改它:

# Change the value of x
# Notice, that we change the assignment itself, a.k.a `x = 9` is now `x = "It's a trap!"`
x_assign.value.n = "It's a trap!"

现在剩下要做的就是将修改后的 ast 对象编译成更有用的东西:

# Compile the new function
new_nine = compile(nine_ast, 'new_nine', 'exec')

您可以使用简单的 exec(如果它在 globals 中,它将替换 'number_nine'),或 exec in,并将其放置在临时模块中:

# Now we need to execute our litle new_nine (which is a code object)
# This to create the modified version in 'm'
import types
m = types.ModuleType('m', 'The m module')
exec new_nine in m.__dict__
m.number_nine()

# Or this to create it in the global scope
exec new_nine
number_nine()

砰!它打印 x: It's a trap!

关于python - 使用 python inspect 查看函数中的局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8732092/

相关文章:

python - 有没有办法更改 Pandas 数据透视表的边距 "All"列位置?

javascript - Selenium/Python Jquery 弹出窗口

python - 在 Jython 中使用时 inspect.py 的问题

intellij-idea - SonarLint 看不到服务器绑定(bind)

python - 是否可以通过代码对象访问内部函数和类?

python - OpenShift,Python 应用程序每 10 分钟运行一次脚本

python - pygame显示自动调整大小

python - 如何在Python类中正确显示 "stub"__objclass__?

python - 获取任意脚本文件的Python docstring

java - 用于检测字符串参数顺序错误的方法调用的注解