获取已安装软件包的描述,而无需实际导入它

时间:2017-02-09 10:31:37

标签: python

如果输入:

import somemodule
help(somemodule)

它将打印出分页包描述。我需要获得与字符串相同的描述,但不将此包导入当前命名空间。这可能吗?肯定是,因为Python中的任何东西都是可能的,但这样做的最优雅/ pythonic方式是什么?

旁注:优雅的方式我的意思是不打开一个单独的过程并捕获它的标准输出......;)

换句话说,有没有办法窥视一个未经过安装但未安装的软件包并获得其描述?也许有importlib.abc.InspectLoader的东西?但我不知道如何让它按照我需要的方式工作。

更新:我不仅要不污染命名空间,还要做到这一点,不要在内存和sys.modules等中留下任何自身或相关模块的痕迹。就像它从未真正导入过一样。

更新:在有人问我为什么需要它之前 - 我想列出所有已安装的python包及其描述。但在此之后我不希望在sys.modules中导入它们,也不想占用内存中过多的空间,因为它们可能有很多。

3 个答案:

答案 0 :(得分:1)

您需要导入模块以获取帮助字符串的原因是,在许多情况下,帮助字符串实际上是在代码中生成的。解析这样一个包的文本来获取字符串是毫无意义的,因为你必须编写一个小的Python解释器来重构实际的字符串。

话虽如此,有些方法可以完全删除基于this answer的临时导入的模块,它总结了2003年左右Python邮件列表中出现的一个主题:http://web.archive.org/web/20080926094551/http://mail.python.org/pipermail/python-list/2003-December/241654.html。此处描述的方法通常仅在模块未在其他地方引用时才有效。否则,模块将被卸载,import将从头开始重新加载,而不是使用现有的sys.modules条目,但模块仍将存在于内存中。

这是一个功能,可以大致完成你想要的功能,如果模块似乎没有被卸载,甚至会打印警告。与链接答案中提出的解决方案不同,此函数确实处理加载模块的所有副作用,包括导入一个包可能会将其他外部包导入sys.modules

import sys, warnings
def get_help(module_name):
    modules_copy = sys.modules.copy()
    module = __import__(module_name)
    h = help(module)
    for modname in list(sys.modules):
        if modname not in modules_copy:
            del sys[modname]
    if sys.getrefcount(module) > 1:
        warnings.warn('Module {} is likely not to be completely wiped'.format(module_name))
    del module
    return h

我在最后一个循环中列出键的原因是,在迭代它时修改字典(或任何其他可迭代的)是不可取的。至少在Python 3中,dict.keys()返回一个由字典本身支持的迭代,而不是冻结的副本。我不确定h = ...return h是否必要,但在最坏的情况下,h只是None

答案 1 :(得分:0)

好吧,如果您只担心保持全局命名空间整洁,您可以随时导入函数:

>>> def get_help():
...     import math
...     help(math)
...
>>> math
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'math' is not defined

答案 2 :(得分:-1)

我建议采用不同的方法,如果我理解正确的话,你希望阅读一部分包而不导入它(即使在具有本地范围的函数中)。我建议这样做的方法是通过访问(python_path)/ Lib / site-packages /(package_name)/并读取相应文件的内容作为导入模块的替代方法,以便Python可以。