簡體   English   中英

是否可以寫入解釋器中運行的 python 代碼中的 sys._getframe() 返回的 python 框架 object?

[英]Is it possible to write to a python frame object as returned by sys._getframe() from python code running within the interpreter?

關於這個問題,解釋器中有一些腳手架來檢查框架對象,可以通過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 ,標志ROREADONLY意味着它的屬性是只讀的。 對於PyGetSetDef ,如果它只有一個 getter,它是只讀的。 這意味着除了f_exc_typef_exc_valuef_exc_tracebackf_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有效,但會影響整個模塊。

NXC 的 f_locals['foo'] 示例有效,因為代碼位於模塊 scope 中。 在這種情況下,f_locals 是 f_globals,而 f_globals 是可修改的,修改會反映在模塊中。

在 function scope 內部,locals() 和 f_locals 是可寫的,但是“[更改可能不會影響解釋器使用的局部變量的值]”。 1這是一種實施選擇。 在 CPython 中,有一個針對局部變量的優化字節碼 LOAD_FAST。 在 Python 中,一旦定義了 function,局部變量(幾乎總是)是已知的,並且 CPython 使用索引查找來獲取變量值,而不是字典查找。

從理論上講,字典查找可以代理該表,但這是一項收效甚微的工作。

“已知局部變量”的例外情況是 function 使用 exec 語句,並且不推薦使用“from module import *”的情況。 對於這些情況,生成的字節碼是不同的,而且速度較慢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM