Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonバイトコードの逆アセンブラ


Python標準ライブラリのdisモジュールは、Pythonバイトコードを人間が読める形式に分解することにより、Pythonバイトコードの分析に役立つさまざまな関数を提供します。これは、最適化の実行に役立ちます。バイトコードは、インタプリタのバージョン固有の実装の詳細です。

dis()関数

関数dis()は、Pythonコードソース、つまりモジュール、クラス、メソッド、関数、またはコードオブジェクトの分解された表現を生成します。

>>> def hello():
print ("hello world")
>>> import dis
>>> dis.dis(hello)
2    0 LOAD_GLOBAL 0 (print)
     3 LOAD_CONST 1 ('hello world')
     6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
     9 POP_TOP
     10 LOAD_CONST 0 (None)
     13 RETURN_VALUE

バイトコード分析APIは、バイトコードクラスで定義されています。そのコンストラクタは、バイトコードを分析するための次のメソッドを持つBytecodeオブジェクトを返します

Bytecode()

これはコンストラクターです。関数、ジェネレータ、メソッド、ソースコードの文字列、またはコードオブジェクトに対応するバイトコードを分析します。これは、多くの関数の便利なラッパーです

>>> string=dis.Bytecode(hello)
>>> for x in string:
      print (x)
Instruction(opname = 'LOAD_GLOBAL', opcode = 116, arg = 0, argval = 'print', argrepr = 'print', offset = 0, starts_line = 2, is_jump_target = False)
Instruction(opname = 'LOAD_CONST', opcode = 100, arg = 1, argval = 'hello world', argrepr = "'hello world'", offset = 3, starts_line = None, is_jump_target = False)
Instruction(opname = 'CALL_FUNCTION', opcode = 131, arg = 1, argval = 1, argrepr = '1 positional, 0 keyword pair', offset = 6, starts_line = None, is_jump_target = False)
Instruction(opname = 'POP_TOP', opcode = 1, arg = None, argval = None, argrepr = '', offset = 9, starts_line = None, is_jump_target = False)
Instruction(opname = 'LOAD_CONST', opcode = 100, arg = 0, argval = None, argrepr = 'None', offset = 10, starts_line = None, is_jump_target = False)
Instruction(opname = 'RETURN_VALUE', opcode = 83, arg = None, argval = None, argrepr = '', offset = 13, starts_line = None, is_jump_target = False)

code_info()

この関数は、Pythonコードオブジェクトの情報を返します。

>>> dis.code_info(hello)
"Name: hello\nFilename: <pyshell#2>\nArgument count: 0\nKw-only arguments: 0\nNumber of locals: 0\nStack size: 2\nFlags: OPTIMIZED, NEWLOCALS, NOFREE\nConstants:\n 0: None\n 1: 'hello world'\nNames:\n 0: print"

show_code()

この関数は、Pythonモジュール、関数、またはクラスの詳細なコード情報を出力します。

>>> dis.show_code(hello)
Name: hello
Filename: <pyshell#2>
Argument count: 0
Kw-only arguments: 0
Number of locals: 0
Stack size: 2
Flags: OPTIMIZED, NEWLOCALS, NOFREE
Constants:
   0: None
   1: 'hello world'
Names:
   0: print

disassemble()

この関数はコードオブジェクトを分解し、次の列に分割された出力を提供します-

  • 各行の最初の命令の行番号

  • ->、

    として示される現在の命令
  • >>、

    で示されるラベル付きの指示
  • 命令のアドレス

  • オペレーションコードネーム

  • 動作パラメータ、および

  • 括弧内のパラメーターの解釈。

>>> codeInString = 'a = 5\nb = 6\nsum = a + b \ nprint("sum = ",sum)'
>>> codeObejct = compile(codeInString, 'sumstring', 'exec')
>>> dis.disassemble(codeObejct)

出力

1    0 LOAD_CONST 0 (5)
     3 STORE_NAME 0 (a)
2    6 LOAD_CONST 1 (6)
     9 STORE_NAME 1 (b)
3    12 LOAD_NAME 0 (a)
     15 LOAD_NAME 1 (b)
     18 BINARY_ADD
     19 STORE_NAME 2 (sum)
4    22 LOAD_NAME 3 (print)
     25 LOAD_CONST 2 ('sum =')
     28 LOAD_NAME 2 (sum)
     31 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
     34 POP_TOP
     35 LOAD_CONST 3 (None)
     38 RETURN_VALUE

get_instructions()

この関数は、提供された関数、メソッド、ソースコード文字列、またはコードオブジェクトの命令に対するイテレータを返します。イテレータは、提供されたコードの各操作の詳細を示すタプルという名前の一連の命令を生成します。

>>> it=dis.get_instructions(code)
>>> for i in it:
      print (i)
Instruction(opname = 'LOAD_CONST', opcode = 100, arg = 0, argval = <code object hello at 0x02A9BA70,
   file "<disassembly>", line 2>, argrepr = '<code object hello at 0x02A9BA70, file "<disassembly>",
   line 2>', offset = 0, starts_line = 2, is_jump_target = False)
Instruction(opname = 'LOAD_CONST', opcode = 100, arg = 1, argval = 'hello', argrepr = "'hello'", offset = 3, starts_line = None, is_jump_target = False)
Instruction(opname = 'MAKE_FUNCTION', opcode = 132, arg = 0, argval = 0, argrepr = '', offset = 6, starts_line = None, is_jump_target = False)
Instruction(opname = 'STORE_NAME', opcode = 90, arg = 0, argval = 'hello', argrepr = 'hello', offset = 9, starts_line = None, is_jump_target = False)
Instruction(opname = 'LOAD_CONST', opcode = 100, arg = 2, argval = None, argrepr = 'None', offset = 12, starts_line = None, is_jump_target = False)
Instruction(opname = 'RETURN_VALUE', opcode = 83, arg = None, argval = None, argrepr = '', offset = 15, starts_line = None, is_jump_target = False)

関数情報は、以下に示すパラメーターを持つタプルのようなオブジェクトの形式です-

手順
バイトコード操作の詳細
オペコード
以下にリストされているオペコード値およびOpcodeコレクションのバイトコード値に対応する操作用の数値コード。
opname
人間が読める形式の操作名
arg
操作に対する数値引数(存在する場合)、それ以外の場合はなし
argval
解決されたarg値(わかっている場合)、それ以外はargと同じ
argrepr
人間が読める形式の操作引数の説明
オフセット
バイトコードシーケンス内で操作のインデックスを開始します
startups_line
行はこのオペコード(存在する場合)で開始され、それ以外の場合はなし
is_jump_target
他のコードがここにジャンプする場合はTrue、それ以外の場合はFalse

  1. WindowsでのPythonプログラミング用のIDE

    この記事では、PythonforWindowsで利用できるさまざまなIDEについて学習します。 Pycharm インタラクティブなPythonコンソール Webフレームワークのサポート より速い屈折時間 開発が少ない Jupyterノートブック ほぼすべてのPythonモジュールとの互換性 スペースとハードウェアの要件が少ない 組み込みのターミナルおよびカーネル機能 さまざまなウィジェットを適用できます ウィングイデ 組み込みのデバッグツール 単体テストのサポート 簡単なコードナビゲーション機能。 コモドイデ サードパーティライブラリのサポート XMLオートコンプ

  2. Pythonコードの最適化のヒント?

    Pythonは他の準拠言語ほど高速でも効率的でもないことは誰もが知っていますが、ただし、Pythonコードがはるかに大きなワークロードを処理できることを示している大企業はたくさんあり、それほど遅くはないことを示しています。このセクションでは、正しいPythonプログラムをさらに高速かつ効率的に実行するために、覚えておくべきヒントをいくつか紹介します。 ヒント1:組み込み関数を使用する Pythonで効率的なコードを書くことはできますが、組み込み関数(Cで書かれている)に勝るものはありません。下の画像は、Python組み込み関数のリストを示しています ヒント2:Pythonの複数の代入を