Ara*_*Fey 5 python cpython stack-frame python-3.x
我试图找出是否有可能解决堆栈帧中的变量(如返回inspect.currentframe()).
换句话说,我正在寻找一个功能
def resolve_variable(variable_name, frame_object):
return value_of_that_variable_in_that_stackframe
Run Code Online (Sandbox Code Playgroud)
例如,请考虑以下代码:
global_var = 'global'
def foo():
closure_var = 'closure'
def bar(param):
local_var = 'local'
frame = inspect.currentframe()
assert resolve_variable('local_var', frame) == local_var
assert resolve_variable('param', frame) == param
assert resolve_variable('closure_var', frame) == closure_var
assert resolve_variable('global_var', frame) == global_var
bar('parameter')
foo()
Run Code Online (Sandbox Code Playgroud)
局部和全局变量平凡通过抬头f_locals和f_globals框架对象的属性:
def resolve_variable(variable_name, frame_object):
try:
return frame_object.f_locals[variable_name]
except KeyError:
try:
return frame_object.f_globals[variable_name]
except KeyError:
raise NameError(varname) from None
Run Code Online (Sandbox Code Playgroud)
但问题是关闭变量.据我所知,它们不存储在像本地和全局变量这样的字典中.更糟糕的是,如果函数实际访问它们,变量只会成为闭包变量(例如通过读取它的值_ = closure_var或者用它来写入它nonlocal closure_var; closure_var = _).所以实际上有3种不同的情况:
global_var = 'global'
def foo():
unused_cvar = 'unused' # actually not a closure variable at all
readonly_cvar = 'closure'
nonlocal_cvar = 'nonlocal'
def bar(param):
nonlocal nonlocal_cvar
local_var = 'local'
_ = readonly_cvar
nonlocal_cvar = 'nonlocal'
frame = inspect.currentframe()
assert resolve_variable('local_var', frame) == local_var
assert resolve_variable('param', frame) == param
assert resolve_variable('unused_cvar', frame) == 'unused'
assert resolve_variable('readonly_cvar', frame) == readonly_cvar
assert resolve_variable('nonlocal_cvar', frame) == nonlocal_cvar
assert resolve_variable('global_var', frame) == global_var
bar('parameter')
foo()
Run Code Online (Sandbox Code Playgroud)
如何重写我的resolve_variable功能以支持所有这些?它甚至可能吗?
通常不可能.Python只保留闭包实际引用的闭包变量.
>>> import inspect
>>> class Demo(object):
... def __del__(self):
... print("Too late, it's gone.")
...
>>> def f():
... a = Demo()
... def g():
... return inspect.currentframe()
... return g
...
>>> frame = f()()
Too late, it's gone.
Run Code Online (Sandbox Code Playgroud)
从这个例子中可以看出,没有希望a从框架中进行检查frame.没了.
至于封闭变量实际使用的框架,通常显示在框架中f_locals.我知道一个奇怪的情况,他们不会,如果框架是一个带有闭包变量的类语句:
>>> def f():
... a = 1
... class Foo(object):
... print(a)
... print(inspect.currentframe().f_locals)
... return Foo
...
>>> f()
1
{'__module__': '__main__', '__qualname__': 'f.<locals>.Foo'}
<class '__main__.f.<locals>.Foo'>
Run Code Online (Sandbox Code Playgroud)
通过实施CPython的挖掘之后(特别是画面的物体,在LOAD_CLASSDEREF操作码和inspect.getclosurevars),我想访问类框架闭包变量的唯一方法将是与ctypes,gc.get_referents或类似手段讨厌.
另请注意,f_locals如果闭包变量值在访问后已更改,则dict可能不是最新的; frame.f_locals再次访问会刷新内容,但在您查看时可能会再次过时.
| 归档时间: |
|
| 查看次数: |
87 次 |
| 最近记录: |