Ist es möglich, ein Python-Frame-Objekt zu schreiben, wie durch sys._getframe () von Python-Code ausgeführt wird innerhalb des Interpreter zurückgegeben?

StackOverflow https://stackoverflow.com/questions/626835

Frage

A propos von Dieser Frage , gibt es ein bisschen von Gerüsten im Interpreter Rahmen Objekte zu untersuchen, die durch sys._getframe() abgerufen werden können. Die Rahmen Objekte erscheinen nur gelesen, aber ich kann nichts offensichtlich in der Dokumentation finden, die dies ausdrücklich erklärt. Kann jemand bestätigen, ob diese Objekte (in irgendeiner Weise) beschreibbar sind oder nur lesen?

import sys

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

if __name__ == '__main__':
    foobar()

Dies gibt ‚foo‘ bei der Ausführung aber der Beitrag unten zeigt die Variable, beschreibbar, wenn sie aus dem aktuellen Frame in einer interaktiven Shell ausgeführt.

War es hilfreich?

Lösung

Von CPython Quelle, 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}
};

Für die PyMemberDef, die Fahnen RO oder READONLY bedeutet es die Attribute schreibgeschützt sind. Für die PyGetSetDef, wenn es nur einen Getter hat, ist es nur lesen. Das bedeutet, alle Attribute aber f_exc_type, f_exc_value, f_exc_traceback und f_trace sind schreibgeschützt nach der Erstellung. Dies spiegelt sich auch in der Dokumentation erwähnt, unter Datenmodell .

Die durch die Attribute bezeichnen Objekte sind nicht unbedingt schreibgeschützt. Sie können dies tun:

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

Obwohl dies in dem Dolmetscher arbeitet, schlägt es innerhalb von Funktionen. Das Ausführungs-Engine verwendet eine separate Anordnung für lokale Variablen (f_fastlocals), die in f_locals auf Zugang verschmolzen wird, aber das Gegenteil ist nicht wahr.

>>> 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
>>>

Auf dem globalen Rahmen bezieht sich f_local auf f_globals, die diesen Trick Arbeit im Interpreter macht. Ändern f_globals funktioniert, aber wirkt sich auf das gesamte Modul.

Andere Tipps

Die f_locals [ 'foo'] Beispiel von NXC funktioniert, weil der Code in Modulbereich ist. In diesem Fall ist f_locals f_globals und f_globals sowohl modifizierbar und Modifikationen sind im Modul reflektiert wird.

Innerhalb von Funktionsumfang, Einheimische () und f_locals beschreibbar ist, aber „[Änderungen nicht die Werte von lokalen Variablen vom Interpreter verwendet beeinflussen können].“ 1 Es ist eine Implementierung Wahl. In CPython gibt es eine optimierte Bytecode für lokale Variablen, LOAD_FAST. In Python sind lokale Variablen (fast immer), sobald die Funktion bekannt ist, definiert ist, und CPython verwendet einen Index-Lookup den Variablenwert, sondern als ein Wörterbuchsuche zu erhalten.

In der Theorie der Wörterbuchsuche konnte Proxy die Tabelle, aber das ist viel Arbeit für wenig Gewinn.

Die Ausnahmen von „lokalen Variablen sind bekannt“ sind, wenn die Funktion eine exec-Anweisung verwendet, und den veralteten Fall von „aus dem Modul import *“. Das erzeugte Byte-Code ist anders, und langsamer, für diese Fälle.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top