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

时间:2016-06-10 15:33:49

标签: python python-2.7 packages

我环顾四周,没有看到解决方案。我想要做的是在运行时获取Python中可用的所有软件包的列表。

我看了看这些:

但他们不是我想要的。

我试图这样做:

import pkgutil
for pkg in pkgutil.walk_packages():
    print pkg #or do something with them...

然而,当我做this时:

import sys
sys.modules.keys()​​​

看来我已经加载了所有我想要做的包,我想要的是当前Python安装可用的所有包+模块的字符串列表而不加载它们我什么时候做的

3 个答案:

答案 0 :(得分:2)

好吧,我很好奇,我挖了一点pkgutil,我想出了这个,这比我想象的要简单得多:

list(pkgutil.iter_modules())

它列出了所有可用作普通文件或zip包的顶级软件包/模块,而不加载它们。但它不会看到其他类型的包,除非它们正确地注册pkgutil内部。

每个返回的条目都是一个3元组:

  • 找到模块的文件查找程序实例
  • 模块的名称
  • 一个布尔值,指定它是常规模块还是包。

返回列表的示例条目:

 (FileFinder('/usr/lib/python3/dist-packages'), 'PIL', True),

我可以确认这没有加载PIL包:

In [11]: sys.modules['PIL']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-11-b0fc0af6cc34> in <module>()
----> 1 sys.modules['PIL']

KeyError: 'PIL'

答案 1 :(得分:1)

我汇总了一种非常粗略的方式来获取此列表(见下文),似乎比pkgutil 更准确。请参阅下面的详细信息。

此外,我发现 loaded_moduleslist-imports, 但是我都没有测试。


我已将我的方法的结果与the answer by spectras进行了比较:

  1. 按光谱(例如modlist2)输出的所有项目都在此处(例如modlist1)的输出中。
  2. modlist1中有很多项目不在modlist2中。 令我惊讶的是,这种差异包括sysmathzlib等模块。 在我的情况下,相应的长度分别为390和327,因此使用pkgutil的方法给出的结果不完整

提取可用模块列表的方法包括:

  1. help的输出捕获为字符串
  2. 从捕获的字符串中删除备用文本
  3. 拆分多列输出

代码在这里:

def modules_list() :
    """Return a list of available modules"""
    import sys
    # Capture output of help into a string
    import io
    stdout_sys = sys.stdout
    stdout_capture = io.StringIO()
    sys.stdout = stdout_capture
    help('modules')
    sys.stdout = stdout_sys
    help_out = stdout_capture.getvalue()
    # Remove extra text from string
    help_out = help_out.replace('.', '')
    help_out = help_out.replace('available modules', '%').replace('Enter any module', '%').split('%')[-2]
    # Split multicolumn output
    help_out = help_out.replace('\n', '%').replace(' ', '%').split('%')
    help_out = list(filter(None, help_out))
    help_out.sort()
    return help_out

答案 2 :(得分:0)

如果您需要所有可用的模块,而不仅仅是在 sys.path 中的所有目录中作为文件存在的模块,那么您可以使用(未​​记录的)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 command line option 启动 Python。

以下是 pkgutil 在 Python 3.9 上找不到的包:

$ 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 的,除了不是解析 stdouthelp('modules'),我已经复制/粘贴了 the code that that function runs(你需要复制/粘贴因为它打印到标准输出,所以没有辅助函数):