我如何在Python脚本内列出所有可用的Python包/模块?

11 浏览
0 Comments

我如何在Python脚本内列出所有可用的Python包/模块?

我看了看,并没有找到解决方案。我想做的是在运行时获取 Python 中所有可用的包的列表。

我查看了以下内容:

但它们不是我要找的。

我尝试做了这个:

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日
0
0 Comments

如果你需要所有可用模块,而不仅是在所有目录中作为文件存在的模块,可以使用(未文档化的)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,没有帮助函数):

0
0 Comments

好的,我很好奇,研究了一下 pkgutil,然后找到了这个,比我预想的简单多了:

list(pkgutil.iter_modules())

它会列出所有顶级包/模块,无论是常规文件还是 zip 包,而不会加载它们。但是,除非它们正确地向 pkgutil 内部注册,否则它将无法识别其他类型的包。

每个返回的条目都是一个带有以下三个项目的 3 元组:

  1. module_finder:找到模块的文件查找器实例
  2. name:模块的名称
  3. 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'

0