我如何在Python脚本内列出所有可用的Python包/模块?
我如何在Python脚本内列出所有可用的Python包/模块?
我看了看,并没有找到解决方案。我想做的是在运行时获取 Python 中所有可用的包的列表。
我查看了以下内容:
- List all the modules that are part of a python package?
- Python package structure
- How to: get list of modules in a package
但它们不是我要找的。
我尝试做了这个:
import pkgutil for pkg in pkgutil.walk_packages(): print(pkg) # or do something with them...
然而,当我执行 这个时:
import sys sys.modules.keys()
看起来我已经加载了所有的包,这不是我想要做的,我想要的是列出当前 Python 安装中所有可用的包+模块的字符串列表,而不必在列出时全部加载。
admin 更改状态以发布 2023年5月21日
如果你需要所有可用模块,而不仅是在所有目录中作为文件存在的模块,可以使用(未文档化的)pydoc.ModuleScanner
(不幸的是,它会加载模块以使其工作):
from pydoc import ModuleScanner import warnings def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) with warnings.catch_warnings(): warnings.simplefilter("ignore") # ignore warnings from importing deprecated modules ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) print(sorted(modules))
pkgutil.iter_modules
的问题在于它不返回所有的包,只返回那些是文件或目录的包,但是CPython使用其他特殊的方式加载了一些模块,这些模块不能仅通过查看文件来检测。
ModuleScanner
的问题在于它返回所有可用的模块,包括您使用 pip install
安装的模块。如果您只需要 Python 自带的包,那么可以使用 -I
命令行选项启动 Python。
这是在 Python 3.9 上 pkgutil
无法找到的包:
$ python3.9 -I Python 3.9.0+ (default, Oct 19 2020, 09:51:18) [GCC 10.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> modules = ... # paste the above code ... >>> import pkgutil >>> sorted(set(modules) - {m.name for m in pkgutil.iter_modules()}) ['_abc', '_ast', '_bisect', '_blake2', '_codecs', '_collections', '_csv', '_datetime', '_elementtree', '_functools', '_heapq', '_imp', '_io', '_locale', '_md5', '_operator', '_peg_parser', '_pickle', '_posixsubprocess', '_random', '_sha1', '_sha256', '_sha3', '_sha512', '_signal', '_socket', '_sre', '_stat', '_statistics', '_string', '_struct', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'array', 'atexit', 'binascii', 'builtins', 'cmath', 'errno', 'faulthandler', 'fcntl', 'gc', 'grp', 'itertools', 'marshal', 'math', 'posix', 'pwd', 'pyexpat', 'select', 'spwd', 'sys', 'syslog', 'time', 'unicodedata', 'xxsubtype', 'zlib']
该回答基于 @sancho.s 的回答,但不是解析 help('modules')
的 stdout
,而是复制粘贴了 该函数运行的代码(您需要复制/粘贴它,因为它会打印到 stdout,没有帮助函数):
好的,我很好奇,研究了一下 pkgutil
,然后找到了这个,比我预想的简单多了:
list(pkgutil.iter_modules())
它会列出所有顶级包/模块,无论是常规文件还是 zip 包,而不会加载它们。但是,除非它们正确地向 pkgutil
内部注册,否则它将无法识别其他类型的包。
每个返回的条目都是一个带有以下三个项目的 3 元组:
module_finder
:找到模块的文件查找器实例name
:模块的名称ispkg
:一个布尔值,指定它是普通模块还是包。
3 元组示例:
(FileFinder('/usr/lib/python3/dist-packages'), 'PIL', True)
我可以确认这不会加载 PIL 包:
In [11]: sys.modules['PIL'] --------------------------------------------------------------------------- KeyError Traceback (most recent call last)in () ----> 1 sys.modules['PIL'] KeyError: 'PIL'