列出属于python包的所有模块?

List all the modules that are part of a python package?

有没有一种直接的方法来查找作为python包的一部分的所有模块? 我发现这个旧的讨论并不是真正的结论,但在推出基于os.listdir()的自己的解决方案之前,我希望得到明确的答案。


是的,你想要基于pkgutil或类似的东西 - 这样你可以对所有的包都一样,无论它们是鸡蛋还是拉链还是那样(os.listdir无济于事)。

1
2
3
4
5
6
7
8
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__

1
2
3
4
5
6
7
8
9
10
11
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


这项工作的正确工具是pkgutil.walk_packages。

要列出系统上的所有模块:

1
2
3
import pkgutil
for importer, modname, ispkg in pkgutil.walk_packages(path=None, onerror=lambda x: None):
    print(modname)

请注意,walk_packages导入所有子包,但不导入子模块。

如果您希望列出某个包的所有子模块,那么您可以使用以下内容:

1
2
3
4
5
6
7
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只列出一级深度的模块。
walk_packages获取所有子模块。
例如,在scipy的情况下,walk_packages返回

1
scipy.stats.stats

而iter_modules只返回

1
scipy.stats

关于pkgutil的文档(http://docs.python.org/library/pkgutil.html)
没有列出中定义的所有有趣函数
/usr/lib/python2.6/pkgutil.py。

也许这意味着这些功能不属于"公共"界面,可能会发生变化。

但是,至少从Python 2.6开始(可能还有早期版本?)
pkgutil附带了一个walk_packages方法,该方法以递归方式遍历所有内容
模块可用。


这对我有用:

1
2
3
4
5
import types

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


这是一种方式,在我的头顶:

1
2
3
>>> 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)>]

它当然可以清理和改进。

编辑:这是一个更好的版本:

1
2
3
4
>>> [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文件中被拉入,那么它取决于你的"部分"包的含义。