オブジェクトの情報を探る(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
ページのトップへ戻る