如何强制更新不同堆栈帧的Python locals()字典?

时间:2016-04-17 15:06:25

标签: python python-internals inspect stackframe locals

在Python 2中(不确定3),本地词典只在实际调用locals()时才会更新。例如,

l=locals()
x=2
l['x']

失败,因为l没有密钥" x"在其中,但

l=locals()
x=2
locals()
l['x']

返回2.

我正在寻找一种强制更新本地词典的方法,但诀窍在于我在不同的堆栈帧中。所以例如我正在寻找

l=locals()
x=2
force_update()
l['x']

我需要编写force_update()函数。我知道从上述函数中我可以通过inspect.currentframe().f_back获取父框架,甚至可以通过inspect.currentframe().f_back.f_locals获取父(未更新)本地文件,但是如何强制更新呢?

如果这看起来很复杂,我的主要目标是编写一个简化"{some} string".format(**dict(globals(),**locals()))的函数,这样我就不必每次都输出,而是可以fmt("{some} string")。这样做我遇到了上面的问题。

编辑:在下面的Martjin回答中,下面基本上是我正在寻找的解决方案。人们可以完全了解他们如何获得被调用者的堆栈帧,这里我通过partial来实现。

from functools import partial
from inspect import currentframe

fmt = partial(lambda s,f: s.format(**dict(globals(),**f.f_locals)),f=currentframe())
x=2
print fmt("{x}") #prints "2"

1 个答案:

答案 0 :(得分:1)

只需访问框架对象上的f_locals 即可触发副本,因此使用inspect.currentframe().f_back.f_locals 就足够了

请参阅frameobject.c实施中的frame_getlocals() function

static PyObject *
frame_getlocals(PyFrameObject *f, void *closure)
{
    PyFrame_FastToLocals(f);
    Py_INCREF(f->f_locals);
    return f->f_locals;
}

PyFrame_FastToLocals是用于将数据从内部数组跟踪局部值复制到字典的函数。 frame_getlocals用于实现frame.f_locals描述符(属性);请参阅frame_getsetlist definition

上面使用的PyFrame_FastToLocalsWithError函数完全 locals()用于生成相同字典的内容(wrapping PyEval_GetLocals function)。