Pythonパッケージの一部であるすべてのモジュールをリストしますか?


107

Pythonパッケージの一部であるすべてのモジュールを見つける簡単な方法はありますか?私はこの古い議論を見つけましたが、これは本当に決定的なものではありませんが、os.listdir()に基づく独自のソリューションを展開する前に、明確な回答が欲しいです。


6
@ S.Lott:より一般的なソリューションが利用可能です。Pythonパッケージは常にファイルシステムのディレクトリにあるとは限りませんが、zip内にある場合もあります。
u0b34a0f6ae 2009年

4
なぜ車輪を再発明するのですか?PythonがPython 4、pkgutilでハイパーモジュールを取得し、それで更新した場合、私のコードは引き続き機能します。利用可能な抽象化を使用するのが好きです。提供されている明白な方法を使用してください。テストされ、動作することがわかっています。それを再実装します..今、あなたは自分ですべてのコーナーケースを見つけて回避する必要があります。
u0b34a0f6ae 2009年

1
@ S.Lott:したがって、アプリケーションが起動するたびに、これをチェックするために内部にインストールされている場合は、独自の卵を解凍しますか?この関数のホイールを再発明するために、私のプロジェクトに対してパッチを提出してください:git.gnome.org/cgit/kupfer/tree/kupfer/plugins.py#n17。卵と通常のディレクトリの両方を考慮してください。20行を超えないでください。
u0b34a0f6ae 2009年

1
@ S.Lott:それが関連していると理解できないのは、理解できないことです。プログラムでこれを発見することは、アプリケーションがユーザーではなくパッケージのコンテンツに関心を持っているということです。
u0b34a0f6ae 2009年

3
もちろん、プログラムで意味します!それ以外の場合は、「os.listdir()を使用した独自のソリューションのロールアウト」については言及しませんでした
static_rtti 2009年

回答:


145

はい、あなたは何かに基づいたもの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

9
これは何をimporter返しpkgutil.iter_modulesますか?これを「ハッキー」に見える代わりに、モジュールをインポートするために使用できます__import__(modname, fromlist="dummy")か?
MestreLion 2013年

29
私は次のようにインポーターを使用することができました:m = importer.find_module(modname).load_module(modname)次にmモジュールですので、例えば:m.myfunc()
chrisleague

@chrisleague私はpython 2.7でurメソッドを使用していましたが、今はpython 3.4に進む必要があるので、python 3ではpkutil.iter_modulesが(module_loader、name、ispkg)ではなく(module_finder、name、ispkg)を生成することがわかります。以前のように機能させるにはどうすればよいですか?
crax

最初の例では次のエラーが発生します:「AttributeError: 'module' object has no attribute ' _path_ '」これはPythonバージョンと関係がありますか?(私はPython 2.7を使用しています)
Apostolos

@Apostolos、パスの両側でアンダースコアを1つだけ使用しています(つまり_path_)。両側に2つ、合計で4つ(つまり__path__)が必要です。
therealmitchconnors

46

このジョブに適したツールは、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メソッドが付属しています。


5
walk_packagesドキュメントに追加さ
メカニカルカタツムリ

1
2番目の例では、次のエラーが発生します。「AttributeError: 'module' object has no attribute ' _path_ '」 -「scipy」ではなく、他のいくつかのパッケージでテストしました。これはPythonバージョンと関係がありますか?(私はPython 2.7を使用しています)
Apostolos 2018

1
@Apostolos:_前と後に2つの下線()が必要です。pathつまり、ではpackage.__path__なくを使用しますpackage._path_。コードを再入力するよりも、コードを切り貼りする方が簡単な場合があります。
unutbu 2018

私がコメントを書いたとき、それらの2つがありました!:)しかし、それらはシステムによって取り除かれました。私の悪い。アンダーコアを3つ入れるべきだった。しかし、イタリックを使用したいのであれば、これで問題ありません。...それは損失損失の状況です。:)とにかく、私がコードを実行するときは、もちろん2つ使用しました。(私はコードをコピーして貼り付けました。)
Apostolos 2018

@Apostolos:変数packageがモジュールではなくパッケージを指していることを確認します。モジュールはファイルですが、パッケージはディレクトリです。すべてのパッケージが持っている__path__属性を(誰かが何らかの理由で属性を削除しない限り...。)
unutbu

2

これは私にとってはうまくいきます:

import types

for key, obj in nltk.__dict__.iteritems():
    if type(obj) is types.ModuleType: 
        print key

1
これは、1パッケージは常に明示的2.パッケージはそのトップレベルの名前空間に他のサードパーティのモジュールをインポートして、トップレベルの名前空間に自分のサブモジュールをインポートしない二つの方法で失敗した
WIM

0

パッケージでライブ編集しているすべてのサブモジュールをリロードする方法を探していました。これは上の回答/コメントの組み合わせなので、コメントではなく回答としてここに投稿することにしました。

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))

-4

これが私の頭の上の方法です。

>>> 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ファイルに組み込まれている場合、必ずしもパッケージのサブディレクトリにあるとは限らない可能性のあるモジュールも検出するため、パッケージの「一部」の意味によって異なります。


すみません、それは無駄です。誤検知は別として、すでにインポートされているパッケージのサブモジュールも検出されます。
u0b34a0f6ae 2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.