2013-10-24 12 views
15

Ich habe große Schwierigkeiten, Pythons Bytecode und sein dis Modul zu verstehen.Wie liest man Python-Bytecode?

import dis 
def func(): 
    x = 1 
dis.dis(func) 

Der obige Code, wenn in dem Interpreter eingegeben erzeugt die folgende Ausgabe:

0 LOAD_CONST     1(1) 
    3 STORE_FAST     0(x) 
    6 LOAD_CONST     0(NONE) 
    9 RETURN_VALUE 

ZB:

Was 3 die Bedeutung von LOAD_CONST, STORE_FAST und die Zahlen wie 0 ist , 6 und 9?

Eine spezifische Ressource, wo ich diese Informationen finden kann, würde sehr geschätzt werden.

+0

Ich bin mir nicht sicher, ob Sie diese Antwort lesen http://StackOverflow.com/a/12673195/973699 – DevC

+0

@DevC Ich habe diese Frage gelesen, aber das Problem war, dass ich nur eine Erklärung für eine sehr "einfache" Funktion wollte , genau wie die, die ich in meiner Frage erwähnt habe, damit ich wenigstens eine Ahnung bekommen konnte, was genau im Byte-Code passiert. –

Antwort

29

Die Zahlen vor den Bytecode-Offsets in die ursprünglichen binären Bytecode sind:

>>> func.__code__.co_code 
'd\x01\x00}\x00\x00d\x00\x00S' 

Einige Bytecode kommen mit zusätzlichen Informationen (Argumente), die wie jedes Bytecode Arbeiten beeinflussen, versetzt die sagt Ihnen, an welcher Position in der Bytestrom Der Bytecode wurde gefunden.

Dem Bytecode LOAD_CONST (ASCII d, Hex 64) folgen zwei zusätzliche Bytes, die beispielsweise einen Verweis auf eine Konstante codieren, die dem Bytecode zugeordnet ist. Als Ergebnis wird der STORE_FAST Opcode (ASCII }, hex 7D) bei Index 3 gefunden.

Die dis module documentation listet auf, was jeder Befehl bedeutet. Für LOAD_CONST heißt es:

Pusht co_consts[consti] auf den Stapel.

was sich auf die Struktur co_consts bezieht, die immer mit einem Codeobjekt vorhanden ist; der Compiler konstruiert, dass:

>>> func.__code__.co_consts 
(None, 1) 

Der Opcode Last Index 1 von dieser Struktur (01 00 Bytes in der Bytecode encode a 1) und dis hat, dass für sie nachgeschlagen; es ist der Wert 1.

Der nächste Befehl wird STORE_FAST wie beschrieben:

Shops TOS in die lokale co_varnames[var_num].

Hier TOS bezieht sich auf Top Of Stack; beachten Sie, dass die LOAD_CONST nur geschoben etwas auf den Stapel, die 1 Wert. co_varnames ist eine andere Struktur; es verweist lokale Variablennamen, der Opcode Referenzen Index 0:

>>> func.__code__.co_varnames 
('x',) 

dis das auch nachgeschlagen, und der Name, den Sie in Ihrem Code verwendet wird, ist x.Somit speicherte dieser Opcode 1 in x.

Weitere LOAD_CONST Lasten None auf den Stapel aus dem Index 0, gefolgt von RETURN_VALUE:

Returns mit TOS an den Aufrufer der Funktion.

Also nimmt diese Anweisung den Anfang des Stapels (mit der Konstante None) und kehrt von diesem Codeblock zurück. None ist der Standard-Rückgabewert für Funktionen ohne explizite return-Anweisung.

Sie ausgelassen etwas aus dem dis Ausgabe, die Zeilennummern:

>>> dis.dis(func) 
    2   0 LOAD_CONST    1 (1) 
       3 STORE_FAST    0 (x) 
       6 LOAD_CONST    0 (None) 
       9 RETURN_VALUE   

Notiere die 2 in der ersten Zeile; Das ist die Zeilennummer in der ursprünglichen Quelle, die den Python-Code enthält, der für diese Anweisungen verwendet wurde. Python-Codeobjekte verfügen über die Attribute co_lnotab und , mit denen Sie Bytecodes zurück zu Zeilennummern in der ursprünglichen Quelle zuordnen können. dis macht dies für Sie bei der Anzeige einer Demontage.

+0

danke für die ausführliche Antwort und den Verweis auf die Dokumente –