Pythonパッケージの一部であるすべてのモジュールを見つける簡単な方法はありますか?私はこの古い議論を見つけましたが、これは本当に決定的なものではありませんが、os.listdir()に基づく独自のソリューションを展開する前に、明確な回答が欲しいです。
Pythonパッケージの一部であるすべてのモジュールを見つける簡単な方法はありますか?私はこの古い議論を見つけましたが、これは本当に決定的なものではありませんが、os.listdir()に基づく独自のソリューションを展開する前に、明確な回答が欲しいです。
回答:
はい、あなたは何かに基づいたものpkgutil
または類似のものを望みます-このようにして、それらが卵やzipなどにあるかどうかに関係なく、すべてのパッケージを同様に扱うことができます(os.listdirは役に立ちません)。
import pkgutil
# this is the package we are inspecting -- for example 'email' from stdlib
import email
package = email
for importer, modname, ispkg in pkgutil.iter_modules(package.__path__):
print "Found submodule %s (is a package: %s)" % (modname, ispkg)
それらをインポートする方法も?__import__
通常どおり使用できます。
import pkgutil
# this is the package we are inspecting -- for example 'email' from stdlib
import email
package = email
prefix = package.__name__ + "."
for importer, modname, ispkg in pkgutil.iter_modules(package.__path__, prefix):
print "Found submodule %s (is a package: %s)" % (modname, ispkg)
module = __import__(modname, fromlist="dummy")
print "Imported", module
importer
返しpkgutil.iter_modules
ますか?これを「ハッキー」に見える代わりに、モジュールをインポートするために使用できます__import__(modname, fromlist="dummy")
か?
m = importer.find_module(modname).load_module(modname)
次にm
モジュールですので、例えば:m.myfunc()
_path_
)。両側に2つ、合計で4つ(つまり__path__
)が必要です。
このジョブに適したツールは、pkgutil.walk_packagesです。
システム上のすべてのモジュールを一覧表示するには:
import pkgutil
for importer, modname, ispkg in pkgutil.walk_packages(path=None, onerror=lambda x: None):
print(modname)
walk_packagesはすべてのサブパッケージをインポートしますが、サブモジュールはインポートしないことに注意してください。
特定のパッケージのすべてのサブモジュールを一覧表示する場合は、次のようなものを使用できます。
import pkgutil
import scipy
package=scipy
for importer, modname, ispkg in pkgutil.walk_packages(path=package.__path__,
prefix=package.__name__+'.',
onerror=lambda x: None):
print(modname)
iter_modulesは、1レベルの深さのモジュールのみをリストします。walk_packagesはすべてのサブモジュールを取得します。たとえば、scipyの場合、walk_packagesは
scipy.stats.stats
iter_modulesが返すのは
scipy.stats
pkgutilに関するドキュメント(http://docs.python.org/library/pkgutil.html)には定義されているすべての興味深い関数がリストされていません。
おそらくこれは、関数が「パブリック」インターフェースの一部ではなく、変更される可能性があることを意味します。
ただし、少なくともPython 2.6(およびおそらく以前のバージョン)では、pkgutilには、利用可能なすべてのモジュールを再帰的にウォークスルーするwalk_packagesメソッドが付属しています。
walk_packages
ドキュメントに追加さ
_
前と後に2つの下線()が必要です。path
つまり、ではpackage.__path__
なくを使用しますpackage._path_
。コードを再入力するよりも、コードを切り貼りする方が簡単な場合があります。
package
がモジュールではなくパッケージを指していることを確認します。モジュールはファイルですが、パッケージはディレクトリです。すべてのパッケージが持っている__path__
属性を(誰かが何らかの理由で属性を削除しない限り...。)
パッケージでライブ編集しているすべてのサブモジュールをリロードする方法を探していました。これは上の回答/コメントの組み合わせなので、コメントではなく回答としてここに投稿することにしました。
package=yourPackageName
import importlib
import pkgutil
for importer, modname, ispkg in pkgutil.walk_packages(path=package.__path__, prefix=package.__name__+'.', onerror=lambda x: None):
try:
modulesource = importlib.import_module(modname)
reload(modulesource)
print("reloaded: {}".format(modname))
except Exception as e:
print('Could not load {} {}'.format(modname, e))
これが私の頭の上の方法です。
>>> import os
>>> filter(lambda i: type(i) == type(os), [getattr(os, j) for j in dir(os)])
[<module 'UserDict' from '/usr/lib/python2.5/UserDict.pyc'>, <module 'copy_reg' from '/usr/lib/python2.5/copy_reg.pyc'>, <module 'errno' (built-in)>, <module 'posixpath' from '/usr/lib/python2.5/posixpath.pyc'>, <module 'sys' (built-in)>]
それは確かにクリーンアップされ、改善される可能性があります。
編集:これは少し良いバージョンです:
>>> [m[1] for m in filter(lambda a: type(a[1]) == type(os), os.__dict__.items())]
[<module 'copy_reg' from '/usr/lib/python2.5/copy_reg.pyc'>, <module 'UserDict' from '/usr/lib/python2.5/UserDict.pyc'>, <module 'posixpath' from '/usr/lib/python2.5/posixpath.pyc'>, <module 'errno' (built-in)>, <module 'sys' (built-in)>]
>>> [m[0] for m in filter(lambda a: type(a[1]) == type(os), os.__dict__.items())]
['_copy_reg', 'UserDict', 'path', 'errno', 'sys']
注:これは、__init__.py
ファイルに組み込まれている場合、必ずしもパッケージのサブディレクトリにあるとは限らない可能性のあるモジュールも検出するため、パッケージの「一部」の意味によって異なります。