从调用命名空间获取局部变量在Python中
我想从一个被调用的函数中获取Python的局部变量。有没有什么办法可以做到这一点?我知道这样做在大多数编程场景中并不合适,但我基本上是在构建一个调试工具。例如:
def show_locals():
# put something in here that shows local_1.
local_1 = 123
show_locals() # I want this to show local_1.
我在show_locals
的主体中应该写什么?如果我需要修改调用语句,最小的修改是什么?
注意:这必须在show_locals
和它的调用者不在同一个模块时也能工作。
3 个回答
0
你可以使用Python内置的函数,dir()或者vars():
vars(对象)
想看看dir()的用法,可以参考这个帖子:这篇文章
使用vars的例子:
>>> class X:
... a=1
... def __init__(self):
... b=2
...
>>>
>>> vars(X)
{'a': 1, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x100488848>}
>>>
>>> vars(X())
{}
有一个可能会让人困惑的地方:新风格的类返回的结果可能和旧风格的不一样
>>> class X(object):
... a=1
... def __init__(self):
... b=2
...
>>>
>>> vars(X)
<dictproxy object at 0x1004a1910>
>>> vars(X())
{}
另外:对于一个已经实例化的类(无论是新风格还是旧风格),如果你在实例化后添加一个变量,vars会像这样返回对象的字典:
>>> x = X()
>>> x.c = 1
>>> vars(x)
{'c': 1}
>>>
7
也许值得提一下,接受的答案中提到的那种从调用者的栈帧读取数据的技巧:
import inspect
def read_from_caller(varname):
frame = inspect.currentframe().f_back
try:
v = frame.f_locals[varname]
return v
finally:
del frame
其实也可以往调用者的命名空间写数据:
import inspect
def write_in_caller(varname, v):
frame = inspect.currentframe().f_back
try:
frame.f_locals[varname] = v
finally:
del frame
如果你把这个放在一个叫做“access_caller”的模块里,那么
import access_caller
access_caller.write_in_caller('y', x)
其实就是一种复杂的写法:
y = x
(我写这个作为一个新的回答,因为我没有足够的声望分数来写评论。)
94
如果你在写一个调试器,你会需要大量使用inspect
这个模块:
def show_callers_locals():
"""Print the local variables in the caller's frame."""
import inspect
frame = inspect.currentframe()
try:
print(frame.f_back.f_locals)
finally:
del frame