Pythonで実行中のコードの情報を取得する方法。例えば関数名とか。

スポンサーリンク



テスト実装していて、ふと「今実行中の関数名を取得するにはどうするんだろう?」と思って調べてみると、いつもお世話になっているQiitaに投稿している人がいた。助かります。 m(._.)m

ちなみにPython2でも3でも同じ方法で取得できました。

>>> def printFuncName():
...     print sys._getframe().f_code.co_name
... 
>>> printFuncName()

printFuncName  

ただ、さすがにこのコードは覚えにくいな・・・。sysモジュールのprivateな関数使ってるし・・・。

ということで「frame」をキーワードに調べてみると、ちゃんと用意されていました。inspectモジュールを使って、もっとスマートに取得できるようです。

inspectモジュールでスタック情報を参照する

inspect: インタプリタスタックから引用します。ちなみに、Python3.5はまたちょっと違うようですが、少なくとも関数の名前のインデックスは同じです。

以下の関数には、戻り値として”フレームレコード”を返す関数があります。 “フレームレコード”は長さ6のタプルで、以下の値を格納しています: フレームオブジェクト、ファイル名、実行中の行番号、関数名、コンテキストのソース行のリスト、ソース行のリストにおける実行中の行のインデックス。

組み込みでよくお目にかかるスタックフレームのPython版ですね。そして以下注釈あり。

フレームレコードの最初の要素などのフレームオブジェクトへの参照を保存すると、循環参照になってしまう場合があります。循環参照ができると、 Python の循環参照検出機能を有効にしていたとしても関連するオブジェクトが参照しているすべてのオブジェクトが解放されにくくなり、明示的に参照を削除しないとメモリ消費量が増大する恐れがあります。

スタック情報から関数名を取得するサンプルコード

ということで、取得したframeは別の変数に保持したりせず、さっさと必要な情報をもらって何もせず返すようにしましょう。

def hogeFunction():  
    f = inspect.currentframe()
    return inspect.getframeinfo(f)[2]

print(hogeFunction())  

上記のコードを実行すると、hogeFunction文字列が出力されます。この関数をそのまま使うと常にhogeFunctionが出力されちゃうので、inspect.getframeinfo(inspect.currentframe())[2]を見たいところに埋め込むのが良いと思います。

ちなみに、getframeinfo()が返すタプルをそのまま出力するとTraceback(filename='<ipython-input-27-52b24ab92ea5>', lineno=3, function='hogeFunction', code_context=[' return inspect.getframeinfo(f)\n'], index=0)となります。

おまけ

inspectモジュールにはその他にも色々と便利そうな関数が用意されていますね。inspectが示す通り、テストや不具合解析なんかで便利に使えそうです。

inspect.ismodule(object)(原文)  
オブジェクトがモジュールの場合真を返します。

inspect.isclass(object)(原文)  
オブジェクトが組み込みか Python が生成したクラスの場合に真を返します。

inspect.ismethod(object)(原文)  
オブジェクトがメソッドの場合真を返します。

inspect.isfunction(object)(原文)  
オブジェクトが Python 関数(lambda 式で生成されたものを含む) の場合に真を返します。

inspect.isgeneratorfunction(object)(原文)  
object が Python のジェネレータ関数の場合真を返します。  
comments powered by Disqus