Перечислите все модули, которые являются частью пакета python?
есть ли простой способ найти все модули, которые являются частью пакета Python? Я нашел эта старая дискуссия, что не совсем убедительно, но я хотел бы иметь определенный ответ, прежде чем я разверну свое собственное решение на основе ОС.listdir().
4 ответа:
Да, вы хотите что-то на основе
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_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, который рекурсивно проходит через все модули доступны.
это работает для меня:
import types for key, obj in nltk.__dict__.iteritems(): if type(obj) is types.ModuleType: print key
вот один из способов, с моей головы:
>>> 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)>]
он, безусловно, может быть очищен и улучшен.
EDIT: вот немного более приятная версия:
>>> [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
файл, так что это зависит от того, что вы подразумеваете под "частью" пакета.