オブジェクトの情報を探る(3) - ソースコードの情報

【 目次 】

cleandoc関数 - ドキュメンテーション文字列をクリーンアップ。

cleandoc関数を使うとオブジェクトのドキュメンテーション文字列をクリーンアップした文字列に変換できる。

公式ドキュメントには

インデントされた docstring から、コードブロックまでのインデントを削除します。 2行目以降では行頭の空白は一様に削除されます。全てのタブはスペースに展開されます。

文字列からインデントを削除する例

import inspect

doc_string="    MyClsクラスはサンプルクラスです"
print inspect.cleandoc(doc_string)

実行結果

MyClsクラスはサンプルクラスです

関数のドキュメンテーション文字列とそのクリーンアップ後の文字列を表示してみる。

import inspect

def avg_func(*args):
    u"""
    複数の引数の値の平均値を求めます
    :arg_list 処理対象の数値のリスト
    :returns  平均値
    """
    total=0
    for num in args:
        total+=num
    return total/len(args)

print " === クリーンアップ前のドキュメンテーション文字列 ==="
print avg_func.__doc__

print " === クリーンアップ後のドキュメンテーション文字列 ==="
print inspect.cleandoc(avg_func.__doc__)

実行結果

 === クリーンアップ前のドキュメンテーション文字列 ===

    複数の引数の値の平均値を求めます
    :arg_list 処理対象の数値のリスト
    :returns  平均値

 === クリーンアップ後のドキュメンテーション文字列 ===
複数の引数の値の平均値を求めます
:arg_list 処理対象の数値のリスト
:returns  平均値

getdoc関数 - オブジェクトのドキュメンテーション文字列を取得

getdoc関数により、オブジェクトのクリーンアップされたドキュメンテーション文字列を取得する事ができる。

import inspect

class MyCls(object):
    "MyClsクラスはサンプルクラスです"

print u"=== MyClsクラスのドキュメンテーション文字列 ==="
print inspect.getdoc(MyCls)
print
print u"=== inspectモジュールのドキュメンテーション文字列 ==="
print inspect.getdoc(inspect)

実行結果

=== MyClsクラスのドキュメンテーション文字列 ===
MyClsクラスはサンプルクラスです

=== inspectモジュールのドキュメンテーション文字列 ===
Get useful information from live Python objects.

This module encapsulates the interface provided by the internal special
attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
It also provides some help for examining source code and class layout.

Here are some of the useful functions provided by this module:

    ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
        isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
        isroutine() - check object types
    getmembers() - get members of an object that satisfy a given condition

    getfile(), getsourcefile(), getsource() - find an object's source code
    getdoc(), getcomments() - get documentation on an object
    getmodule() - determine the module that an object came from
    getclasstree() - arrange classes so as to represent their hierarchy

    getargspec(), getargvalues(), getcallargs() - get info about function arguments
    formatargspec(), formatargvalues() - format an argument spec
    getouterframes(), getinnerframes() - get info about frames
    currentframe() - get the current stack frame
    stack(), trace() - get info about frames on the stack or in a traceback

getcomments関数 - オブジェクトのコメント行を取得

getcomments関数により、クラス,関数,メソッド,モジュールの先頭にあるコメント行 (複数行) を、単一の文字列として取得する事ができる。

# coding: UTF-8

import inspect

# MyClsクラス
class MyCls(object):
    pass

print u"=== MyClsクラスのコメント行 ==="
print inspect.getcomments(MyCls)
print
print u"=== inspectモジュールのコメント行 ==="
print inspect.getcomments(inspect)

実行結果

=== MyClsクラスのコメント行 ===
# MyClsクラス

=== inspectモジュールのコメント行 ===
# -*- coding: iso-8859-1 -*-

getfile関数 - オブジェクトを定義しているモジュールのファイル名を取得

getfile関数により、オブジェクトの定義されているモジュールのファイル名を取得する事ができる。

公式ドキュメントには

オブジェクトを定義している (テキストまたはバイナリの) ファイルの名前を返します。オブジェクトが組み込みモジュール、クラス、関数の場合は TypeError 例外が発生します。

「組み込みモジュール、クラス、関数の場合は TypeError 例外が発生します。」とある。
試しにクラス、関数のファイル名を取得してみる。

import inspect

def func():
    pass

class MyCls(object):
    pass

print inspect.getfile(func)
print inspect.getfile(MyCls)

正常にソースファイルのファイル名が表示できる。
では、標準モジュール(標準ライブラリのモジュール)のオブジェクトの場合はどうだろう?

# 標準モジュールのモジュールオブジェクト
print inspect.getfile(inspect), type(inspect)
# 標準モジュールのクラスオブジェクト
print inspect.getfile(inspect.ArgInfo), type(inspect.ArgInfo)
# 標準モジュールの関数オブジェクト
print inspect.getfile(inspect.getfile), type(inspect.getfile)

実行結果

pythonのインストールデレクトリ\lib\inspect.pyc <type 'module'>
pythonのインストールデレクトリ\lib\inspect.pyc <type 'type'>
pythonのインストールデレクトリ\lib\inspect.py <type 'function'>

これも問題ない。

しかし、ファイルの拡張子について注目してみると「py」であったり「pyc」であったりする。
関数の戻り値が、「コンパイルされたファイル」の場合もあるので注意。

でも、

import sys
inspect.getfile(sys)

を実行すると、エラーが発生。

実行結果

TypeError: <module 'sys' (built-in)> is a built-in module

Python 標準ライブラリ — Python 2.7.x ドキュメント によると

Python プログラマが直接アクセスできないシステム機能へのアクセス機能を提供する (Cで書かれた) 組み込みモジュール

という文言が出てくる。

組み込みモジュールの意味は、
組込み関数組込み型が定義されているモジュールなどのCで書かれた特別なモジュールなどを指すのだろう。

組込み関数lenや組込み型intで試してみると

print inspect.getfile(len)

実行結果

TypeError: <built-in function len> is not a module, class, method, function, traceback, frame, or code object
print inspect.getfile(int)

実行結果

    raise TypeError('{!r} is a built-in class'.format(object))
TypeError: <module '__builtin__' (built-in)> is a built-in class

とTypeErrorが発生する。

では、変数xに対してはどうだろう?

x=10
print inspect.getfile(x)

x="abc"
print inspect.getfile(x)

TypeErrorとなる。
しかし、

x = func

x = MyCls

とした場合は

print inspect.getfile(x)

でエラーは発生しない。

これはxに代入された値が前者の場合は組込みの型(のインスタンス)や関数であったためにエラーとなったが、後者の場合にはユーザ定義の(組込みでは無い)型や関数のためエラーにはならない。

さらに、ユーザ定義のインスタンスオブジェクトの場合はどうだろう?

x = MyCls()
print inspect.getfile(x)

実行結果

TypeError: <__main__.MyCls object at 0x0000000002573780> is not a module, class, method, function, traceback, frame, or code object

インスタンスオブジェクトの場合は組込みであろうと無かろうとエラーが発生するようだ。

getsourcefile関数 - オブジェクトを定義しているモジュールのソースファイル名を取得

getsourcefile関数を使ってオブジェクトの定義されてているモジュールのソースファイル名を取得する事ができる。

getfile関数との違いはバイナリファイル(拡張子がpyc)では無く必ずソースファイル名が返される事。

import inspect

print inspect.getfile(inspect.ArgInfo)
print inspect.getsourcefile(inspect.ArgInfo)

実行結果

pythonのインストールデレクトリ\lib\inspect.pyc
pythonのインストールデレクトリ\lib\inspect.py

公式ドキュメント によると

オブジェクトを定義している Python ソースファイルの名前を返します。オブジェクトが組み込みのモジュール、クラス、関数の場合には、 TypeError 例外が発生します。

これも、変数xが定義されているモジュールのソースファイル名を取得しようとして

class MyCls(object):
    pass

x=MyCls
inspect.getsourcefile(x)

は、xの値がユーザ定義のクラスオブジェクトであるので問題無いが

x=MyCls()
inspect.getsourcefile(x)

とするとxの値がインスタンスオブジェクトであるため、エラーになってしまうので注意。

getsourcelines関数 - オブジェクトのソース行のリストと開始行番号を取得

公式ドキュメント によると

オブジェクトのソース行のリストと開始行番号を返します。引数にはモジュール、クラス、メソッド、関数、トレースバック、フレーム、コードオブジェクトを指定することができます。戻り値は指定したオブジェクトに対応するソースコードのソース行リストと元のソースファイル上での開始行となります。ソースコードを取得できない場合は IOError が発生します。

ユーザ定義クラスMyClsのソース行のリストと開始行番号を表示してみる。

# coding: UTF-8

import inspect

class MyCls(object):
    def method(self):
        pass

print inspect.getsourcelines(MyCls)

実行結果

(['class MyCls(object):\n', '    def method(self):\n', '        pass\n'], 5)

getsource関数 - オブジェクトのソースコードを取得

公式ドキュメント によると

オブジェクトのソースコードを返します。引数にはモジュール、クラス、メソッド、関数、トレースバック、フレーム、コードオブジェクトを指定することができます。ソースコードは単一の文字列で返します。ソースコードを取得できない場合は IOError が発生します。

inspectモジュールのgetsource関数自身のソースを表示させてみると

import inspect

print inspect.getsource(inspect.getsource)

実行結果

def getsource(object):
    """Return the text of the source code for an object.

    The argument may be a module, class, method, function, traceback, frame,
    or code object.  The source code is returned as a single string.  An
    IOError is raised if the source code cannot be retrieved."""
    lines, lnum = getsourcelines(object)
    return string.join(lines, '')

関数内部でgetsourcelines関数を呼んでいるのがわかる。

ページのトップへ戻る