2012-01-04 76 views
1

,查看局部變量我無法弄清楚如何檢查使用我猜測它涉及到用行走和getinnerframe的getouterframe框架層次當前正在執行的功能inspect/inspect_shell使用python檢查的功能

,但我在幾個問題上感到困惑。

鑑於這種例子 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,我看到getinnerframes在當前幀上不起作用(它需要一個跟蹤(可能?)),而當前幀沒有「跟蹤」。和getouterframes(如果我正在考慮這個倒退)似乎只能得到與我的功能無關的幀。在 'nine.py'

>> 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)] 

回答

1

Inspect Shell的作者在這裏:)你可能需要使x從全局命名空間訪問。 Inspect Shell實質上會讓你進入正在運行的腳本的全局命名空間,所以如果從那裏無法獲得一些數據,那麼實現它將非常棘手。

所以真的建議是,使x全球,那麼你應該能夠改變它,你的number_nine()函數將返回。

希望有幫助!

2

這有點棘手,但考慮到源代碼(或一個良好的Python反編譯器),你可以做到這一點

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(將取代「number_nine」如果是在globals),或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!

+1

在我的例子nine.py已經運行(注意while循環),我需要檢查該過程。 Inspect_shell應該通過套接字公開所有進程。 (請參閱inspect_shell文檔的鏈接)我無法停止並重新編譯我的現實世界問題的任何部分。我試圖讓我的問題更清楚。感謝您的答覆。 – Paul 2012-01-04 23:02:19