列出 Python 包中的所有模块?

是否有一种直接的方法来查找作为 python 包一部分的所有模块?我已经找到了 这个旧的讨论,它并不是真正的决定性因素,但是在我基于 os.listdir ()推出我自己的解决方案之前,我希望能有一个确切的答案。

102278 次浏览

Here's one way, off the top of my head:

>>> 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文件中,所以这取决于您所说的“部分”包的含义。

是的,您需要一些基于 pkgutil或类似的东西——这样您就可以对待所有的包,无论它们是在鸡蛋或拉链或其他(其中 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

这个工作的正确工具是 pkgutil.walk _ package。

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

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

请注意 walk _ package 导入所有子包,但不导入子模块。

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

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 _ module 只列出了一级深度的模块。 Walk _ package 获取所有子模块。 In the case of scipy, for example, walk_packages returns

scipy.stats.stats

而 iter _ module 只返回

scipy.stats

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

也许这意味着这些函数不是“公共”接口的一部分,可能会发生变化。

然而,至少在 Python 2.6(或者更早的版本?) Pkgutil 附带了 walk _ package 方法,该方法递归地遍历所有 模块可用。

这对我有用:

import types


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

我正在寻找一种方法,以重新加载所有子模块,我正在编辑我的软件包现场。它是上面的答案/评论的组合,所以我决定把它作为一个答案而不是一个评论贴在这里。

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