dis モジュールは CPython バイトコード (bytecode) を逆アセンブルすることでバイトコードの解析をサポートします。このモジュールが入力として受け取る CPython バイトコードはファイル Include/opcode.h に定義されており、コンパイラとインタプリタが使用しています。
CPython implementation detail:
バイトコードは CPython インタプリタの実装詳細です! Python のバージョン間でバイトコードの追加や、削除、変更がないという保証はありません。このモジュールを使用することによって Python の異なる VM または異なるリリースの間で動作すると考えるべきではありません。
例: 以下の関数 myfunc() を考えると
def myfunc(alist):
return len(alist)
myfunc() の逆アセンブル結果を得るために次のコマンドを使うことができます
>>> dis.dis(myfunc)
2 0 LOAD_GLOBAL 0 (len)
3 LOAD_FAST 0 (alist)
6 CALL_FUNCTION 1
9 RETURN_VALUE
(“2”は行番号です)。
dis モジュールは次の関数と定数を定義します:
bytesource オブジェクトを逆アセンブルします。 bytesource はモジュール、クラス、関数、あるいはコードオブジェクトのいずれかを示します。モジュールに対しては、すべての関数を逆アセンブルします。クラスに対しては、すべてのメソッドを逆アセンブルします。単一のコード列に対しては、バイトコード命令ごとに 1 行を出力します。オブジェクトが与えられない場合は、最後のトレースバックを逆アセンブルします。
トレースバックのスタックの先頭の関数を逆アセンブルします。 Noneが渡された場合は最後のトレースバックを使います。例外を引き起こした命令が表示されます。
コードオブジェクトを逆アセンブルします。 lasti が与えられた場合は、最後の命令を示します。出力は次のようなカラムに分割されます:
パラメータの解釈は、ローカル変数とグローバル変数の名前、定数の値、分岐先、比較命令を認識します。
disassembleの別名。よりタイプしやすく、以前のPythonリリースと互換性があります。
命令コード名のリスト。バイトコードをインデックスに使って参照できます。
バイトコードから命令コード名へのマッピング辞書。
すべての比較命令の名前のリスト。
定数パラメータを持つバイトコードのリスト。
自由変数にアクセスするバイトコードのリスト。
名前によって属性にアクセスするバイトコードのリスト。
相対ジャンプ先を持つバイトコードのリスト。
絶対ジャンプ先を持つバイトコードのリスト。
ローカル変数にアクセスするバイトコードのリスト。
ブール命令のバイトコードのリスト。
現在Pythonコンパイラは次のバイトコード命令を生成します。
コンパイラにコードの終わりを知らせます。インタプリタでは使われません。
なにもしないコード。バイトコードオプティマイザでプレースホルダとして使われます。
スタックの先頭 (TOS) の要素を取り除きます。
スタックの先頭の 2 つの要素を入れ替えます。
スタックの二番目と三番目の要素の位置を 1 つ上げ、先頭を三番目へ下げます。
スタックの二番目、三番目および四番目の位置を 1 つ上げ、先頭を四番目に下げます。
スタックの先頭にある参照の複製を作ります。
単項命令はスタックの先頭を取り出して操作を適用し、結果をスタックへプッシュし戻します。
TOS = +TOS に対応します。
TOS = -TOS に対応します。
TOS = not TOS に対応します。
TOS = `TOS` に対応します。
TOS = ~TOS に対応します。
TOS = iter(TOS) に対応します。
二項命令はスタックの先頭(TOS)と先頭から二番目の要素をスタックから取り除きます。命令を実行し、スタックへ結果をプッシュし戻します。
TOS = TOS1 ** TOS に対応します。
TOS = TOS1 * TOS に対応します。
from __future__ import division が有効でないときの TOS = TOS1 / TOS に対応します。
TOS = TOS1 // TOS に対応します。
from __future__ import division が有効なときの TOS = TOS1 / TOS に対応します。
TOS = TOS1 % TOS に対応します。
TOS = TOS1 + TOS に対応します。
TOS = TOS1 - TOS に対応します。
TOS = TOS1[TOS] に対応します。
TOS = TOS1 << TOS に対応します。
TOS = TOS1 >> TOS に対応します。
TOS = TOS1 & TOS に対応します。
TOS = TOS1 ^ TOS に対応します。
TOS = TOS1 | TOS に対応します。
インプレース命令はTOSとTOS1を取り除いて結果をスタックへプッシュするという点で二項命令と似ています。しかし、TOS1がインプレース命令をサポートしている場合には操作が直接TOS1に行われます。また、操作結果のTOSは (常に同じというわけではありませんが) 元のTOS1と同じオブジェクトになることが多いです。
インプレースの TOS = TOS1 ** TOS に対応します。
インプレースの TOS = TOS1 * TOS に対応します。
from __future__ import division が有効でないときのインプレースの TOS = TOS1 / TOS に対応します。
インプレースの TOS = TOS1 // TOS に対応します。
from __future__ import division が有効なときのインプレースの TOS = TOS1 / TOS に対応します。
インプレースの TOS = TOS1 % TOS に対応します。
インプレースの TOS = TOS1 + TOS に対応します。
インプレースの TOS = TOS1 - TOS に対応します。
インプレースの TOS = TOS1 << TOS に対応します。
インプレースの TOS = TOS1 >> TOS に対応します。
インプレースの TOS = TOS1 & TOS に対応します。
インプレースの TOS = TOS1 ^ TOS に対応します。
インプレースの TOS = TOS1 | TOS に対応します。
スライス命令コードは最大 3 つのパラメータを取ります。
TOS = TOS[:] に対応します。
TOS = TOS1[TOS:] に対応します。
TOS = TOS1[:TOS] に対応します。
TOS = TOS2[TOS1:TOS] に対応します。
スライス代入はさらにもう 1 つのパラメータを必要とします。他の文と同じく、これらはスタックに何もプッシュしません。
TOS[:] = TOS1 に対応します。
TOS1[TOS:] = TOS2 に対応します。
TOS1[:TOS] = TOS2 に対応します。
TOS2[TOS1:TOS] = TOS3 に対応します。
del TOS[:] に対応します。
del TOS1[TOS:] に対応します。
del TOS1[:TOS] に対応します。
del TOS2[TOS1:TOS] に対応します。
TOS1[TOS] = TOS2 に対応します。
del TOS1[TOS] に対応します。
その他の命令コード。
対話モードのための式文に対応します。TOSはスタックから取り除かれ表示されます。非対話モードにおいては、式文は POP_STACK で終了しています。
PRINT_ITEM と似ていますが、TOSから二番目の要素をTOSにあるファイル互換オブジェクトへ出力します。これは拡張print文で使われます。
PRINT_NEWLINE と似ていますが、TOSのファイル互換オブジェクトに改行を表示します。これは拡張print文で使われます。
list.append(TOS1, TOS) を呼びます。リスト内包表記を実装するために使われます。
現在のスコープのローカルな名前空間(locals)への参照をスタックにプッシュします。これはクラス定義のためのコードで使われます: クラス本体が評価された後、localsはクラス定義へ渡されます。
関数の呼び出し元へTOSを返します。
'_' で始まっていないすべてのシンボルをモジュールTOSから直接ローカル名前空間へロードします。モジュールはすべての名前をロードした後にポップされます。この命令コードは from module import * に対応します。
exec TOS2,TOS1,TOS に対応します。コンパイラは指定されなかったオプションのパラメータを None で埋めます。
ブロックスタックからブロックを一つ取り除きます。フレームごとにブロックのスタックがあり、ネストしたループやtry文などを表しています。
finally 節を終了します。インタプリタは例外を再送出しなければならないかどうか、あるいは、関数から return して外側の次のブロックに続くかどうかを再度判断します。
新しいクラスオブジェクトを作成します。TOSはメソッド辞書、TOS1は基底クラスの名前のタプル、TOS2はクラス名です。
with 式ブロックを抜けるときに、スタックをクリーンアップします。スタックの先頭は 1–3 個の値で、それらはなぜ/どのように finally 節に到達したかを表しています:
これらの値の下には、コンテキストマネージャーの __exit__() 結合メソッド (bound method) である EXIT があります。
最後のケースでは、 EXIT(TOP, SECOND, THIRD) が呼ばれ、それ以外では EXIT(None, None, None) が呼ばれます。
EXIT はスタックから取り除かれ、その上の値は順序を維持したまま残されます。加えて、スタックが例外処理中であることを示し、 かつ 関数呼び出しが true 値を返した場合、 END_FINALLY が例外を再送出することを防ぐため、この情報は削除されます (“zapped”)。 (しかし、 non-local goto は再開されます)
以下の命令コードはすべて引数を必要とします。引数は 2 バイトで、最上位バイトが後になります。
name = TOS に対応します。 namei はコードオブジェクトの属性 co_names における name のインデックスです。コンパイラは可能ならば STORE_FAST または STORE_GLOBAL を使おうとします。
del name に対応します。 namei はコードオブジェクトの co_names 属性へのインデックスです。
TOS を count 個の個別の値にアンパックして、右から左の順にスタックに置きます。
count 個の要素を順番を保ちながら複製します。実装上の制限から、 count は1から5の間(5を含む)でなければなりません。
TOS.name = TOS1 に対応します。 namei は co_names における名前のインデックスです。
del TOS.name に対応します。 co_names へのインデックスとして namei を使います。
STORE_NAME と同じように動作しますが、 name をグローバルとして保存します。
DELETE_NAME と同じように動作しますが、グローバルの name を削除します。
co_consts[consti] をスタックにプッシュします。
co_names[namei] に関連付けられた値をスタックにプッシュします。
スタックから count 個の要素を消費してタプルを作り出し、できたタプルをスタックにプッシュします。
BUILD_TUPLE と同じように動作しますが、リストを作り出します。
スタックに新しい辞書オブジェクトをプッシュします。辞書は count 個のエントリを持つサイズに設定されます。
TOSを getattr(TOS, co_names[namei]) と入れ替えます。
ブール命令を実行します。命令名は cmp_op[opname] にあります。
モジュール co_names[namei] をインポートします。 TOS と TOS1 がポップされ、 __import__() の fromlist と level 引数になります。モジュールオブジェクトはスタックへプッシュされます。現在の名前空間は影響されません: 適切な import 文のためには、後続の STORE_FAST 命令が名前空間を変更します。
TOS にあるモジュールから属性 co_names[namei] をロードします。作成されたオブジェクトはスタックにプッシュされ、後続の STORE_FAST 命令によって保存されます。
バイトコードカウンタを delta だけ増加させます。
TOSが真ならば、 delta だけバイトコードカウンタを増加させます。TOSはスタックに残されます。
TOSが偽ならば、 delta だけバイトコードカウンタを増加させます。TOSは変更されません。
バイトコードカウンタを target に設定します。
TOS はイテレータです。その next() メソッドを呼び出します。新しい値が yield された場合は、それをスタックにプッシュします (イテレータはその下に残されます)。イテレータの呼び出しで要素が尽きたことが示された場合は、 TOS がポップされます。そして、バイトコードカウンタが delta だけ増やされます。
co_names[namei] という名前のグローバルをスタック上にロードします。
ループのためのブロックをブロックスタックにプッシュします。ブロックは現在の命令から delta バイトの大きさを占めます。
try-except節からtryブロックをブロックスタックにプッシュします。 delta は最初のexceptブロックを指します。
try-except節からtryブロックをブロックスタックにプッシュします。 delta はfinallyブロックを指します。
key, value のペアを辞書に格納します。 key と value をポップする一方、辞書はスタックに残されます。
ローカルな co_varnames[var_num] への参照をスタックにプッシュします。
TOSをローカルな co_varnames[var_num] の中に保存します。
ローカルな co_varnames[var_num] を削除します。
セルと自由変数の記憶領域のスロット i に含まれるセルへの参照をプッシュします。 i が co_cellvars の長さより小さければ、変数の名前は co_cellvars[i] です。そうでなければ co_freevars[i - len(co_cellvars)] です。
セルと自由変数の記憶領域のスロット i に含まれるセルをロードします。セルが持つオブジェクトへの参照をスタックにプッシュします。
セルと自由変数の記憶領域のスロット i に含まれるセルへTOSを保存します。
この命令コードは廃止されました。
例外を発生させます。 argc はraise文へ与えるパラメータの数を0から3の範囲で示します。ハンドラはTOS2をトレースバック、TOS1をパラメータ、TOSを例外として探します。
関数を呼び出します。 argc の下位バイトは位置パラメータの数を、上位バイトはキーワードパラメータの数を示します。スタック上では、最初にキーワードパラメータが見つかります。それぞれのキーワード引数に対しては、値がキーより上に来ます。スタック上のキーワードパラメータの下に位置パラメータがあり、最も右のパラメータが先頭になります。スタック上のパラメータの下には、呼び出される関数オブジェクトが置かれます。すべての関数引数をポップし、関数自体もスタックから取り除き、戻り値をプッシュします。
新しい関数オブジェクトをスタックにプッシュします。 TOSは関数に関連付けられたコードです。関数オブジェクトはTOSの下にある argc デフォルトパラメータをもつように定義されます。
新しい関数オブジェクトを作り出し、その func_closure スロットを設定し、スタックにプッシュします。 TOSは関数に関連付けられたコードで、TOS1 はクロージャの自由変数に対するセルを格納したタプルです。関数はセルの前にある argc デフォルトパラメータも持っています。
スライスオブジェクトをスタックにプッシュします。 argc は2あるいは3でなければなりません。 2ならば slice(TOS1, TOS) がプッシュされます。 3ならば slice(TOS2, TOS1, TOS) がプッシュされます。これ以上の情報については、 slice() 組み込み関数を参照してください。
デフォルトの 2 バイトに収まりきらない大きな引数を持つあらゆる命令コードの前に置かれます。 ext は追加の 2 バイトを保持し、後続の命令コードの引数と組み合わされます。それらは 4 バイト引数を構成し、 ext はその最上位バイトです。
関数を呼び出します。 argc は CALL_FUNCTION と同じように解釈されます。スタックの先頭の要素は可変引数リストを含んでおり、その後にキーワード引数と位置引数が続きます。
関数を呼び出します。 argc は CALL_FUNCTION と同じように解釈されます。スタックの先頭の要素はキーワード引数辞書を含んでおり、その後に明示的なキーワード引数と位置引数が続きます。
関数を呼び出します。 argc は CALL_FUNCTION と同じように解釈されます。スタックの先頭の要素はキーワード引数辞書を含んでおり、その後に変数引数のタプルが続き、さらに明示的なキーワード引数と位置引数が続きます。
これは実際の命令コードではありません。引数を取らない命令コード < HAVE_ARGUMENT と、引数を取る命令コード >= HAVE_ARGUMENT の分割行を表します。