オブジェクトの情報を探る(4) - モジュールオブジェクト
【 目次 】
モジュールオブジェクトの属性
モジュールオブジェクトの属性で何がアクセスできるのか、
公式ドキュメントの表より、モジュールオブジェクトの部分より抜き出すと。
属性 | 説明 |
---|---|
__doc__ | ドキュメント文字列 |
__file__ | ファイル名 (組み込みモジュールには存在しません) |
getmodule関数 - オブジェクトを定義しているモジュールのモジュールオブジェクトを取得
公式ドキュメントによると
オブジェクトを定義しているモジュールを推測します。
import文を使ってモジュールオブジェクトを取得する
外部のモジュールのモジュールオブジェクトを取得するにはimport文を使えば良い。
import inspect import math print inspect.ismodule(math),type(math)
実行結果
True <type 'module'>
でも、mathモジュールからsin関数のみをimportしていた場合には
from math import sin
getmodule関数を使ってsin関数が定義されているモジュールオブジェクトを取得できる。
import inspect math_module=inspect.getmodule(sin) print inspect.ismodule(math_module),type(math_module)
実行結果
True <type 'module'>
そして、モジュールが持っているシンボルにアクセスする事ができる。
print math_module.pi
実行結果
3.14159265359
次のコードは、pprintモジュールに含まれる関数名の一覧をgetmembers関数を使って表示する例である。
import inspect import pprint object_list=inspect.getmembers(pprint,inspect.isfunction) for func_name, _ in object_list: print func_name
実行結果
_perfcheck _recursion _safe_repr _sorted isreadable isrecursive pformat pprint saferepr
組込みオブジェクトのモジュールオブジェクトは?
では組込み関数や組込み型の定義されているモジュールオブジェクトはどうかというと、
len関数やint型を調べてみると
print inspect.getmodule(len) print inspect.getmodule(int)
実行結果
<module '__builtin__' (built-in)> <module '__builtin__' (built-in)>
そうだった組込み関数には__builtin__に定義されていて__builtins__という名前でアクセスできるんだったけ
print __builtins__.len("abc") print __builtins__.int(10)
実行結果
3 10
現在実行中のモジュールのモジュールオブジェクトを取得する
メインモジュールやサブモジュール等での現在実行中のモジュールのモジュールオブジェクトを取得するにはどうしたら良いだろう。
x=u"変数の値"
と変数が定義されているモジュールに対して
import inspect module_object=inspect.getmodule(x)
としても
print module_object
実行結果
None
Noneが帰ってくるだけで変数xが定義されているモジュールのモジュールオブジェクトは取得できない。
モジュールにクラスや関数が定義されていれば
class MyCls(object): pass def func(): pass
module_object=inspect.getmodule(MyCls)
や
module_object=inspect.getmodule(func)
で
print module_object
実行結果
<module '__main__' from 'ソースファイルのファイル名(フルパス)'>
モジュールオブジェクトを取得できる。
またユーザ定義のクラスのインスタンスの場合には
subモジュールにクラスが定義してあって
sub.py
class MyCls(object): pass
main.py
my_inst=sub.MyCls() module_object=inspect.getmodule(my_inst) print module_object
実行結果
<module 'sub' from 'モジュールまでのパス\sub.py'>
のようにインスタンスを生成したモジュールでは無くて、インスタンスの属するクラスを定義しているモジュールのモジュールオブジェクトが取得できる。
いずれにしても目的とは関係無い関数やクラスやインスタンスが必要では面白くない。
いろいろ悩んだ末にみつけたのが
現在、実行中のフレームオブジェクトを取得するcurrentframe関数を利用してそのフレームのモジュールオブジェクトを取得する事。
import inspect def func(): module_object=inspect.getmodule(inspect.currentframe()) print "sub.func",module_object
mainモジュール
import inspect import sub module_object=inspect.getmodule(inspect.currentframe()) print "main:", module_object sub.func()
実行結果
main: <module '__main__' from 'モジュールまでのパス\main.py'> sub.func <module 'sub' from 'モジュールまでのパス\sub.py'>
mainモジュールから、実行中のフレームオブジェクトのモジュールオブジェクトを取得すればmainモジュールのモジュールオブジェクトが、subモジュールに定義されている関数から、実行中のフレームオブジェクトのモジュールオブジェクトを取得すればsubモジュールのモジュールオブジェクトが、取得できる事になる。
mainモジュールのモジュールオブジェクト__main__
ところで、上記の実行結果<module '__main__' from 'モジュールまでのパス\main.py'>
からすると、mainモジュールのモジュールオブジェクトとして__main__という隠れたモジュールが存在すると推測される。
でもmainモジュールより
print __main__
を実行しても
実行結果
NameError: name '__main__' is not defined
となってアクセスできない。
では組込み関数等が定義されている__builtin__モジュールに対して__builtins__でアクセスできるように、別の名前でmainモジュールのモジュールオブジェクトが定義されているのかとdir関数で探してみても
print dir()
実行結果
['__builtins__', '__doc__', '__file__', '__name__', '__package__']
でてこない。
しかし、__main__をimportする事で
import __main__ print __main__
実行結果
<module '__main__' from 'ソースファイルのファイル名(フルパス)'>
メインモジュールの変数へアクセス
x=u"変数の値" print __main__.x
実行結果
変数の値
メインモジュールのソースコードを表示
import __main__ import inspect print inspect.getsource(__main__)
実行結果
# coding: UTF-8 import __main__ import inspect print inspect.getsource(__main__)
mainモジュールの場合には、__main__をimportする事でモジュールオブジェクトを取得できるようだ。
__main__は公式ドキュメント
によると「トップレベルのスクリプト環境」だそうだ。
よくでてくる、あれ
if __name__ == "__main__":
はこういう意味だったのか。
ところで、getmodule関数は
def getmodule(object, _filename=None):
となっていて引数_filenameを指定する事もできるようだ。
長々とここまで話してきてこれが何の役に立つかって?
さぁ、わからん。
ちょっと気になって調べてみただけサ!
getmoduleinfo -path で指定したファイルのモジュールの情報を取得
モジュールのパスを引数にして、getmoduleinfo関数を呼び出すとそのモジュールについての情報を取得する事ができる。
import inspect import os moduleinfo = inspect.getmoduleinfo(inspect.getfile(os)) print moduleinfo
実行結果
ModuleInfo(name='os', suffix='.pyc', mode='rb', module_type=2)
osモジュールの替わりにsysモジュール等の一部の組込みモジュールを指定した場合は、もともとシステムに組み込まれたモジュールのためモジュールのパスは存在せず、getfileでパスが取得できないのでエラーになってしまうので注意。
getmoduleinfo関数は、inspect.ModuleInfo型((name, suffix, mode, module_type)
形式の名前付きタプル)の値を返すようで。
print type(moduleinfo)
実行結果
<class 'inspect.ModuleInfo'>
公式ドキュメントによると
name はパッケージ名を含まないモジュール名、 suffix はファイル名からモジュール名を除いた残りの部分 (ドット区切りの拡張子であってはなりません)、 mode は open() で指定されるファイルモード ('r' または 'rb')、 module_type はモジュールタイプを示す整数で、 imp で定義している定数のいずれかが指定されます。モジュールタイプについては imp を参照してください。
各要素をドットを使って属性としてアクセスしたり
print moduleinfo.name print moduleinfo.suffix print moduleinfo.mode print moduleinfo.module_type
配列のようにインデックスでアクセスしたり
print moduleinfo[0] print moduleinfo[1] print moduleinfo[2] print moduleinfo[3]
できる。
実行結果
os .pyc rb 2
getmodulename関数 - path で指定したファイルの、パッケージ名を含まないモジュール名を取得
公式ドキュメントによると
path で指定したファイルの、パッケージ名を含まないモジュール名を返します。この処理は、インタープリタがモジュールを検索する時と同じアルゴリズムで行われます。ファイルがこのアルゴリズムで見つからない場合には None が返ります。
import inspect import os modulename = inspect.getmodulename(inspect.getfile(os)) print modulename
実行結果
os