我环顾四周,没有看到解决方案。我想要做的是在运行时获取Python中可用的所有软件包的列表。
我看了看这些:
但他们不是我想要的。
我试图这样做:
import pkgutil
for pkg in pkgutil.walk_packages():
print pkg #or do something with them...
然而,当我做this时:
import sys
sys.modules.keys()
看来我已经加载了所有不我想要做的包,我想要的是当前Python安装可用的所有包+模块的字符串列表而不加载它们我什么时候做的
答案 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_modules 和list-imports, 但是我都没有测试。
我已将我的方法的结果与the answer by spectras进行了比较:
modlist2
)输出的所有项目都在此处(例如modlist1
)的输出中。modlist1
中有很多项目不在modlist2
中。
令我惊讶的是,这种差异包括sys
,math
,zlib
等模块。
在我的情况下,相应的长度分别为390和327,因此使用pkgutil
的方法给出的结果不完整。提取可用模块列表的方法包括:
help
的输出捕获为字符串代码在这里:
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 的,除了不是解析 stdout
的 help('modules')
,我已经复制/粘贴了 the code that that function runs(你需要复制/粘贴因为它打印到标准输出,所以没有辅助函数):