Pythonのinspectの使い方|関数や変数を解析する方法を解説する

スポンサーリンク

Pythonの inspect モジュール は、生きているオブジェクトとそのソースコードのイントロスペクションを提供します。

また、プログラム中で使用されているクラスや関数のイントロスペクションも提供します。

inspectモジュールは、その中の関数やメソッドを利用して、ソースコードを取得し、必要なライブラリドキュメントを抽出し、解析することができます

このモジュールは、特定のユーザーのプログラム内の関数、クラス、モジュールに関する情報を取得するために使用されます。

これは、モジュールのプロパティ、モジュールのクラス/メソッドなどに関する検査を実行することによって利用できるようになります。

スポンサーリンク

Python inspect モジュールの機能性

  • モジュールのイントロスペクション を行う。
  • モジュール内のクラスのイントロスペクション `
  • クラス内のメソッド/関数のイントロスペクション とします。
  • クラスのオブジェクトのイントロスペクション
  • クラスのソースの取得 `クラスのオブジェクトの取得
  • メソッド/関数のソースを取得する
  • メソッドシグネチャの取得 について
  • クラスの文字列の記録 の作成
  • クラス階層のイントロスペクション の作成
  • ランタイム環境におけるフレームとスタックのイントロスペクション

1. モジュールのイントロスペクション

最初に、イントロスペクションのためのクラス/関数と一緒にサンプルモジュールを作成する必要があります(例:test.py)

test.py

def funct(arg1, arg2 = 'default', *args):
    #module-level function
    x = arg1 * 1
    return x
 
class P(object):
 
 
    def __init__(self, city):
        self.city = city
 
    def get_city(self):
 
        return self.city
 
obj_p = P('sample_instance')
 
class Q(P):
 
 
 
    def country(self):
       return ("Hello")
    def get_country(self):
 
        return 'Q(' + self.city + ')'

次に、作成したモジュールを inspect.getmembers() 関数でイントロスペクションします。

注意:サンプルモジュールを含む Python ファイルとイントロスペクションのコードを含むファイルは、同じディレクトリに配置する必要があります。

モジュールのイントロスペクションを行うためのコード

import inspect
import test
 
for city, data in inspect.getmembers(test):
    if city.startswith('__'):
        continue
    print('{} : {!r}'.format(city, data))

結果は以下の通りです。

P : <class 'test.p'="">
Q : <class 'test.q'="">
funct : <function 0x000001ed62a2eaf0="" at="" funct="">
obj_p : <test.p 0x000001ed62a6a640="" at="" object="">

2. モジュール内のクラスのイントロスペクション

getmembers()関数とisclass` プロパティ識別子を使用して、モジュール内のクラスをインスペクションすることができます

import inspect
import test
 
for key, data in inspect.getmembers(test, inspect.isclass):
    print('{} : {!r}'.format(key, data))

結果は以下の通りです。

出力: “`
P :
Q :


---



### 3. クラス内のメソッド/関数のイントロスペクション

getmembers()` 関数と `isfunction` プロパティ識別子を用いて、モジュール内のクラスをインスペクションすることができます。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_451190"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python keyword">import</code> <code class="python plain">inspect</code></div><div class="line number2 index1 alt1"><code class="python keyword">from</code> <code class="python plain">pprint </code><code class="python keyword">import</code> <code class="python plain">pprint</code></div><div class="line number3 index2 alt2"><code class="python keyword">import</code> <code class="python plain">test</code></div><div class="line number4 index3 alt1"> </div><div class="line number5 index4 alt2"><code class="python plain">pprint(inspect.getmembers(test.P, inspect.isfunction))</code></div></div></td></tr></tbody></table></div></div></div>

出力します。

出力: ```
[('__init__', <function 0x000001d519ca7ca0="" at="" p.__init__="">),
 ('get_city', <function 0x000001d519ca7d30="" at="" p.get_city="">)]

4. クラスのオブジェクトのイントロスペクション

import inspect
from pprint import pprint
import test
 
result = test.P(city='inspect_getmembers')
pprint(inspect.getmembers(result, inspect.ismethod))

結果は以下の通りです。

[('__init__',
  <bound 0x00000175a62c5250="" <test.p="" at="" method="" object="" of="" p.__init__="">&gt;),
 ('get_city',
  <bound 0x00000175a62c5250="" <test.p="" at="" method="" object="" of="" p.get_city="">&gt;)]

5. 5. クラスのソースの取得

getsource()`関数は特定のモジュール/クラスのソースを返します。

import inspect
import test
 
print(inspect.getsource(test.Q))

結果は、以下の通りです。

出力: “`
class Q(P):

def country(self):
return (“Hello”)
def get_country(self):

return ‘Q(‘ + self.city + ‘)’


---



### 6. メソッド/関数のソースの検索

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_136628"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python keyword">import</code> <code class="python plain">inspect</code></div><div class="line number2 index1 alt1"><code class="python keyword">import</code> <code class="python plain">test</code></div><div class="line number3 index2 alt2"> </div><div class="line number4 index3 alt1"><code class="python functions">print</code><code class="python plain">(inspect.getsource(test.Q.get_city))</code></div></div></td></tr></tbody></table></div></div></div>

結果を出力すると、以下の様になります。

def get_city(self):

return self.city


---



### 7. メソッドのシグネチャを取得する

inspect.signature()`メソッドはメソッドのシグネチャを返すので、ユーザーはメソッドに渡された引数の種類を簡単に理解することができます。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_866967"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python keyword">import</code> <code class="python plain">inspect</code></div><div class="line number2 index1 alt1"><code class="python keyword">import</code> <code class="python plain">test</code></div><div class="line number3 index2 alt2"> </div><div class="line number4 index3 alt1"><code class="python functions">print</code><code class="python plain">(inspect.signature(test.funct))</code></div></div></td></tr></tbody></table></div></div></div>

出力します。

(arg1, arg2=’default’, *args)


---



### 8. あるクラスに対する文字列の文書化

inspectモジュールの `getdoc()` 関数は、エンドユーザーに表現するために特定のクラスとその関数を抽出します。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_654543"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python keyword">import</code> <code class="python plain">inspect</code></div><div class="line number2 index1 alt1"><code class="python keyword">import</code> <code class="python plain">test</code></div><div class="line number3 index2 alt2"> </div><div class="line number4 index3 alt1"><code class="python functions">print</code><code class="python plain">(</code><code class="python string">'P.__doc__:'</code><code class="python plain">)</code></div><div class="line number5 index4 alt2"><code class="python functions">print</code><code class="python plain">(test.P.__doc__)</code></div><div class="line number6 index5 alt1"><code class="python functions">print</code><code class="python plain">()</code></div><div class="line number7 index6 alt2"><code class="python functions">print</code><code class="python plain">(</code><code class="python string">'Documentation String(P):'</code><code class="python plain">)</code></div><div class="line number8 index7 alt1"><code class="python functions">print</code><code class="python plain">(inspect.getdoc(test.P))</code></div></div></td></tr></tbody></table></div></div></div>

出力します。

P.doc:
Implementation of class P

Documentation String(P):
Implementation of class P


---



### 9. クラス階層の調査

getclasstree()` メソッドは、クラスとその依存関係の階層を返します。このメソッドは、与えられたクラスからタプルとリストを用いてツリー構造を作成します。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_230909"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python keyword">import</code> <code class="python plain">inspect</code></div><div class="line number2 index1 alt1"><code class="python keyword">import</code> <code class="python plain">test</code></div><div class="line number3 index2 alt2"> </div><div class="line number4 index3 alt1"><code class="python keyword">class</code> <code class="python plain">S(test.Q):</code></div><div class="line number5 index4 alt2"><code class="python spaces">    </code><code class="python keyword">pass</code></div><div class="line number6 index5 alt1"> </div><div class="line number7 index6 alt2"><code class="python keyword">class</code> <code class="python plain">T(S, test.P):</code></div><div class="line number8 index7 alt1"><code class="python spaces">    </code><code class="python keyword">pass</code></div><div class="line number9 index8 alt2"> </div><div class="line number10 index9 alt1"><code class="python keyword">def</code> <code class="python plain">print_class_tree(tree, indent</code><code class="python keyword">=</code><code class="python keyword">-</code><code class="python value">1</code><code class="python plain">):</code></div><div class="line number11 index10 alt2"><code class="python spaces">    </code><code class="python keyword">if</code> <code class="python functions">isinstance</code><code class="python plain">(tree, </code><code class="python functions">list</code><code class="python plain">):</code></div><div class="line number12 index11 alt1"><code class="python spaces">        </code><code class="python keyword">for</code> <code class="python plain">node </code><code class="python keyword">in</code> <code class="python plain">tree:</code></div><div class="line number13 index12 alt2"><code class="python spaces">            </code><code class="python plain">print_class_tree(node, indent</code><code class="python keyword">+</code><code class="python value">1</code><code class="python plain">)</code></div><div class="line number14 index13 alt1"><code class="python spaces">    </code><code class="python keyword">else</code><code class="python plain">:</code></div><div class="line number15 index14 alt2"><code class="python spaces">        </code><code class="python functions">print</code><code class="python plain">( </code><code class="python string">'  '</code> <code class="python keyword">*</code> <code class="python plain">indent, tree[</code><code class="python value">0</code><code class="python plain">].__name__ )</code></div><div class="line number16 index15 alt1"> </div><div class="line number17 index16 alt2"> </div><div class="line number18 index17 alt1"><code class="python keyword">if</code> <code class="python plain">__name__ </code><code class="python keyword">=</code><code class="python keyword">=</code> <code class="python string">'__main__'</code><code class="python plain">:</code></div><div class="line number19 index18 alt2"><code class="python spaces">    </code><code class="python functions">print</code><code class="python plain">( </code><code class="python string">'P, Q, S, T:'</code><code class="python plain">)</code></div><div class="line number20 index19 alt1"><code class="python spaces">    </code><code class="python plain">print_class_tree(inspect.getclasstree([test.P, test.Q, S, T]))</code></div></div></td></tr></tbody></table></div></div></div>

出力されます。

P, Q, S, T:
object
P
T
Q
S
T


---



### 10. 実行時環境におけるフレームとスタックのイントロスペクション

inspectモジュールは、プログラムの実行中に関数の動的環境も検査します。関数は主にコールスタックとコールフレームを扱う。

`currentframe()` は、現在実行中の関数のスタックの最上位にあるフレームを描画します。`getargvalues()` は、引数の名前とフレームからのローカル値のディクショナリを含むタプルとして結果を返します。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_491142"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python keyword">import</code> <code class="python plain">inspect</code></div><div class="line number2 index1 alt1"> </div><div class="line number3 index2 alt2"><code class="python keyword">def</code> <code class="python plain">recurse(threshold):</code></div><div class="line number4 index3 alt1"><code class="python spaces">    </code><code class="python plain">x </code><code class="python keyword">=</code> <code class="python string">'.'</code> <code class="python keyword">*</code> <code class="python plain">threshold</code></div><div class="line number5 index4 alt2"><code class="python spaces">    </code><code class="python functions">print</code> <code class="python plain">(threshold, inspect.getargvalues(inspect.currentframe()))</code></div><div class="line number6 index5 alt1"><code class="python spaces">    </code><code class="python keyword">if</code> <code class="python plain">threshold &lt;</code><code class="python keyword">=</code> <code class="python value">0</code><code class="python plain">:</code></div><div class="line number7 index6 alt2"><code class="python spaces">        </code><code class="python keyword">return</code></div><div class="line number8 index7 alt1"><code class="python spaces">    </code><code class="python plain">recurse(threshold </code><code class="python keyword">-</code> <code class="python value">1</code><code class="python plain">)</code></div><div class="line number9 index8 alt2"><code class="python spaces">    </code><code class="python keyword">return</code></div><div class="line number10 index9 alt1"> </div><div class="line number11 index10 alt2"><code class="python keyword">if</code> <code class="python plain">__name__ </code><code class="python keyword">=</code><code class="python keyword">=</code> <code class="python string">'__main__'</code><code class="python plain">:</code></div><div class="line number12 index11 alt1"><code class="python spaces">    </code><code class="python plain">recurse(</code><code class="python value">4</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div></div>

出力。

4 ArgInfo(args=[‘threshold’], varargs=None, keywords=None, locals={‘threshold’: 4, ‘x’: ‘….’})
3 ArgInfo(args=[‘threshold’], varargs=None, keywords=None, locals={‘threshold’: 3, ‘x’: ‘…’})
2 ArgInfo(args=[‘threshold’], varargs=None, keywords=None, locals={‘threshold’: 2, ‘x’: ‘..’})
1 ArgInfo(args=[‘threshold’], varargs=None, keywords=None, locals={‘threshold’: 1, ‘x’: ‘.’})
0 ArgInfo(args=[‘threshold’], varargs=None, keywords=None, locals={‘threshold’: 0, ‘x’: ”})
“`

まとめ

以上、Pythonのinspectモジュールが提供する機能を理解しました。

タイトルとURLをコピーしました