2017-02-09 25 views
3

如果你输入:得到一个安装包的描述不实际导入它

import somemodule 
help(somemodule) 

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

边注:通过优雅的方式,我的意思,而无需打开一个单独的进程,并捕获标准输出...;)

换句话说,是有办法窥视到一个未汇入,但安装的软件包,并查看其描述?也许与importlib.abc.InspectLoader?但我不知道如何让它按我需要的方式工作。

更新:我不需要不污染命名空间,但也可以做到这一点,而不会留下任何自己或依赖模块的痕迹在内存和sys.modules等。像它从来没有真正导入。

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

+0

感谢您的澄清。这使得它成为可能 –

回答

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 
+0

麻烦的是,它仍然加载在内存和'sys.modules'中。我不清楚这一点,所以我会更新这个问题。 –

-1

我会建议不同的方法,如果我理解正确的话,你想读一个包的一部分,而不导入它(甚至在一个局部范围的函数内)。我建议一种方法是通过访问(python_path)/ Lib/site-packages /(package_name)/并读取各个文件的内容作为导入模块的替代方法,以便Python可以。

+0

这有时会起作用,但是很多Python docstrings都是从格式化表达式到设置'__doc__'属性的完全不同的代码生成的。在这些情况下,您将最终重新实现解释器来获取文档字符串。 –

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

+0

感谢日志,我会试一试。但仍然感觉有点脆弱。因此,我倾向于使用单独的进程来导入模块,将所需的字符串回滚,然后删除此进程(es)。这似乎是错误的证据,而且我不会在获取数据时阻止我的主流程,我认为这需要一段时间。 –

+0

你的方式确实更可靠。你应该发布你自己的答案。此外,[这个问题](http://stackoverflow.com/q/42142660/2988730)来自上面的答案。 –

+0

一旦我的解决方案正常工作,我将发布我的答案。 –

相关问题