Skip to main content
 首页 » 编程设计

python之是否可以从解释器中运行的 python 代码写入 sys._getframe() 返回的 python 框架对象

2025年05月04日10yyy_WW

关于 This question , 解释器中有一些脚手架来检查框架对象,可以通过 sys._getframe() 检索。框架对象似乎是只读的,但我在文档中找不到任何明确说明这一点的明显内容。有人可以确认这些对象是可写的(以某种方式)还是只读的?

import sys 
 
def foobar(): 
    xx='foo' 
    ff = sys._getframe() 
    ff.f_locals['xx'] = 'bar' 
    print xx 
 
if __name__ == '__main__': 
    foobar() 

这会在运行时打印出“foo”,但下面的帖子演示了在交互式 shell 中从当前帧运行时该变量是可写的。

请您参考如下方法:

来自 CPython 源代码,Objects/frameobject.c:

static PyMemberDef frame_memberlist[] = { 
    {"f_back",      T_OBJECT,       OFF(f_back),    RO}, 
    {"f_code",      T_OBJECT,       OFF(f_code),    RO}, 
    {"f_builtins",  T_OBJECT,       OFF(f_builtins),RO}, 
    {"f_globals",   T_OBJECT,       OFF(f_globals), RO}, 
    {"f_lasti",     T_INT,          OFF(f_lasti),   RO}, 
    {"f_exc_type",  T_OBJECT,       OFF(f_exc_type)}, 
    {"f_exc_value", T_OBJECT,       OFF(f_exc_value)}, 
    {"f_exc_traceback", T_OBJECT,   OFF(f_exc_traceback)}, 
    {NULL}    /* Sentinel */ 
}; 
... 
static PyGetSetDef frame_getsetlist[] = { 
    {"f_locals",    (getter)frame_getlocals, NULL, NULL}, 
    {"f_lineno",    (getter)frame_getlineno, 
                    (setter)frame_setlineno, NULL}, 
    {"f_trace",     (getter)frame_gettrace, (setter)frame_settrace, NULL}, 
    {"f_restricted",(getter)frame_getrestricted,NULL, NULL}, 
    {0} 
}; 

对于 PyMemberDef,标志 RO 或 READONLY 表示它的属性是只读的。对于 PyGetSetDef,如果它只有一个 getter,则它是只读的。这意味着除 f_exc_type、f_exc_value、f_exc_traceback 和 f_trace 之外的所有属性在创建后都是只读的。这也在文档中提到,在 Data model 下.

属性引用的对象不一定是只读的。你可以这样做:

>>> f = sys._getframe() 
>>> f.f_locals['foo'] = 3 
>>> foo 
3 
>>> 

虽然这在解释器中有效,但在函数内部却失败了。执行引擎为局部变量 (f_faSTLocals) 使用一个单独的数组,在访问时将其合并到 f_locals 中,但反之则不然。

>>> def foo(): 
...   x = 3 
...   f = sys._getframe() 
...   print f.f_locals['x'] 
...   x = 4 
...   print f.f_locals['x'] 
...   d = f.f_locals 
...   x = 5 
...   print d['x'] 
...   f.f_locals 
...   print d['x'] 
... 
>>> foo() 
3 
4 
4 
5 
>>> 

在全局框架上,f_local 引用f_globals,这使得这个技巧在解释器中起作用。修改 f_globals 有效,但会影响整个模块。