オブジェクトの情報を探る(7) - コードオブジェクト
【 目次 】
コードオブジェクト
コードオブジェクトって何?
公式ドキュメントには
- 3. データモデル — Python 2.7.x ドキュメント
コードオブジェクトは バイトコンパイルされた (byte-compiled) 実行可能な Python コード、別名バイトコード(bytecode) を表現します。
「Python/C API リファレンスマニュアル」には
CのAPIまで深入りしたくないのでここまでにして、
コンパイルされたバイトコードをオブジェクトとしてアクセスできるらしい。
そしてそのコードオブジェクトの属性よりソースコードのいろいろな情報が得られるという事。
コードオブジェクトの属性
コードオブジェクトの属性で何がアクセスできるかというと
公式ドキュメントの表より、
コードオブジェクトの部分を抜き出すと
属性 | 説明 |
---|---|
co_argcount | 引数の数 (* や ** 引数は含まない) |
co_code | コンパイルされたバイトコードそのままの文字列 |
co_consts | バイトコード中で使用している定数のタプル |
co_filename | コードオブジェクトを生成したファイルのファイル名 |
co_firstlineno | Python ソースコードの先頭行 |
co_flags | 以下の値の組み合わせ: 1=optimized , 2=newlocals , 4=*arg , 8=**arg |
co_lnotab | 行番号からバイトコードインデックスへの変換表を文字列にエンコードしたもの |
co_name | コードオブジェクトが定義されたときの名前 |
co_names | ローカル変数名のタプル |
co_nlocals | ローカル変数の数 |
co_stacksize | 必要とされる仮想マシンのスタックスペース |
co_varnames | 引数名とローカル変数名のタプル |
コードオブジェクトは、フレームオブジェクトや関数オブジェクトの属性などから取得する事ができる。
以下のコードは関数のコードオブジェエクトの各属性を表示する例である。
def func(arg1, arg2): l_var = "l_var" return arg1 + arg2 + l_var attr_dict = { "co_argcount":u"引数の数", # "co_code":u"コンパイルされたバイトコード文字列", "co_consts":u"バイトコード中で使用している定数のタプル", "co_filename":u"ファイルのファイル名", "co_firstlineno":u"ソースコードの先頭行", "co_flags":u"以下の値の組み合わせ: 1=optimized , 2=newlocals , 4=*arg , 8=**arg", # "co_lnotab":u"行番号からバイトコードインデックスへの変換表を文字列にエンコードしたもの", "co_name":u"関数名", "co_names":u"ローカル変数名のタプル", "co_nlocals":u"ローカル変数の数", "co_stacksize":u"必要とされる仮想マシンのスタックスペース", "co_varnames":u"引数名とローカル変数名のタプル" } code_object = func.func_code for attr_name, attr_discript in sorted(attr_dict.iteritems()): print attr_discript print attr_name, "=", getattr(code_object, attr_name)
実行結果
引数の数 co_argcount = 2 バイトコード中で使用している定数のタプル co_consts = (None, 'l_var') ファイルのファイル名 co_filename = C:\Rd\Python\pleiades-e4.4-python-jre_20140926\pleiades\workspace\Python2Test\src\tmp.py ソースコードの先頭行 co_firstlineno = 3 以下の値の組み合わせ: 1=optimized , 2=newlocals , 4=*arg , 8=**arg co_flags = 67 関数名 co_name = func ローカル変数名のタプル co_names = () ローカル変数の数 co_nlocals = 3 必要とされる仮想マシンのスタックスペース co_stacksize = 2 引数名とローカル変数名のタプル co_varnames = ('arg1', 'arg2', 'l_var')
ソースコードの取得
コードオブジェクトからソースコード文字列を取得するには inspectモジュールのgetsource関数を使って
import inspect print "コードオブジェクトよりソースコードを取得" source_text = inspect.getsource(code_object) print source_text
実行結果
コードオブジェクトよりソースコードを取得 def func(arg1, arg2): l_var = "l_var" return arg1 + arg2 + l_var