有没有一种直接的方法来查找属于python包的所有模块?我发现this old discussion,这并不是真正的结论,但在推出基于os.listdir()的自己的解决方案之前,我很想得到明确的答案。
答案 0 :(得分:129)
是的,你想要基于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
答案 1 :(得分:40)
这项工作的正确工具是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只列出一级深度的模块。 walk_packages获取所有子模块。 例如,在scipy的情况下,walk_packages返回
scipy.stats.stats
而iter_modules只返回
scipy.stats
关于pkgutil(http://docs.python.org/library/pkgutil.html)的文档 没有列出中定义的所有有趣函数 /usr/lib/python2.6/pkgutil.py。
也许这意味着这些功能不属于“公共”界面,可能会发生变化。
但是,至少从Python 2.6开始(可能还有早期版本?) pkgutil附带了一个walk_packages方法,该方法以递归方式遍历所有内容 模块可用。
答案 2 :(得分:3)
这对我有用:
import types
for key, obj in nltk.__dict__.iteritems():
if type(obj) is types.ModuleType:
print key
答案 3 :(得分: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 :(得分:-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)>]
它当然可以清理和改进。
编辑:这是一个稍微好一点的版本:
>>> [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
文件中被拉入,也会找到可能不一定位于软件包子目录中的模块,因此它取决于什么你的意思是“包的一部分”。