【问题标题】:How to have win32com code completion in IPython?如何在 IPython 中完成 win32com 代码?
【发布时间】:2015-01-15 10:12:28
【问题描述】:

通过

import win32com.client
wordapp = win32com.client.gencache.EnsureDispatch('Word.Application')

我可以得到一个 Word Application 对象记录,例如here。但是ipython的自动补全不知道那个API,有没有办法添加呢?

【问题讨论】:

  • 您必须使用文档或 COM 浏览器来熟悉 API。 python 对象只是代理对象,如果你dir 它只会显示__special__ 方法。在您的情况下,有很好的文档可用,所以应该不会太难。
  • @Dabrion 虽然这引发了一个更普遍的问题,是否有办法自动将格式良好的文档链接到dir...我将不得不考虑更多
  • 我不这么认为,尝试所有可能的方法名称似乎是不可行的。所以这个责任在于 com 对象,当你得到句柄时它应该提供一个方法列表。我记得这个功能(com 浏览器?)。使用 Windows 的东西已经有一段时间了。所以我恐怕不得不向你推荐文档以获取详细信息。
  • @Dabrion 哦不,蛮力是个坏主意。我的意思是,一些使用例如的智能逻辑msdn.microsoft.com/en-us/library/bb244515.aspx 获取实际可用的名称。我对COM知之甚少,所以你提到的浏览器是我必须先阅读的东西......

标签: python autocomplete ipython win32com


【解决方案1】:

快速解决方案

也许在 IPython 中实现代码完成的最简单方法(使用 6.2.1 测试,请参阅 the answer below 了解适用于 7.1 的 sn-p)和 Jupyter 运行以下 sn-p:

from IPython.utils.generics import complete_object
import win32com.client

@complete_object.when_type(win32com.client.DispatchBaseClass)
def complete_dispatch_base_class(obj, prev_completions):
    try:
        ole_props = set(obj._prop_map_get_).union(set(obj._prop_map_put_))
        return list(ole_props) + prev_completions
    except AttributeError:
        pass

长篇小说

this guide 中概述了更多细节,win32com 附带一个脚本,makepy.py 用于生成与给定 COM 对象的类型库对应的 Python 类型。

对于 Word 2016,我们将按以下步骤进行:

C:\Users\username\AppData\Local\Continuum\Anaconda3\pkgs\pywin32-221-py36h9c10281_0\Lib\site-packages\win32com\client>python makepy.py -i "Microsoft Word 16.0 Object Library"

Microsoft Word 16.0 Object Library
 {00020905-0000-0000-C000-000000000046}, lcid=0, major=8, minor=7
 >>> # Use these commands in Python code to auto generate .py support
 >>> from win32com.client import gencache
 >>> gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 7)

makepy.py 的位置当然取决于您的 Python 发行版。同一目录下的脚本combrowse.py,可用于查找可用类型库的名称。

有了它,win32com.client 将自动使用生成的类型,而不是原始的IPyDispatch,此时,自动完成功能可用于例如IPython 或 Jupyter,因为感兴趣的 COM 对象实际上发布了它的可用属性和方法(这不是必需的)。

现在,在您的情况下,通过调用 EnsureDispatch 而不是 Dispatch,该过程的 makepy 部分会自动执行,因此您确实应该能够在 IPython 中为已发布的方法获得代码完成:

但请注意,虽然这确实为方法提供了代码补全,但对于属性则不然。可以使用_prop_map_get_ 属性检查那些。例如,wordapp.Selection.Range.Font._prop_map_get_ 给出了字体的所有可用属性。

如果使用 IPython 的要求不高,另请注意 PythonWin shell(位于 \pkgs\pywin32\Lib\site-packages\pythonwin\Pythonwin.exe 附近)具有对属性和方法的内置代码完成支持。

这本身就表明在 IPython 中同样可以实现。

具体来说,自动补全的逻辑又依赖于_prop_map_get_,可以在scintilla.view.CScintillaView._AutoComplete 中找到。另一方面,IPython 6.2.1 中的代码完成由core.completer.IPCompleter 处理。 IPython.utils.generics.complete_object 提供了用于添加自定义代码完成器的 API,如上面的第一个解决方案所示。一个问题是,complete_object 基于simplegeneric,对于任何给定类型只能提供一个完成者。幸运的是,makepy 生成的所有类型都将继承自 win32com.client.DispatchBaseClass

如果这成为一个问题,也可以完全绕过complete_object,只需将以下五行添加到core.completer.Completion.attr_matches,手动修补IPython:

try:
    ole_props = set(obj._prop_map_get_).union(set(obj._prop_map_put_))
    words += list(ole_props)
except AttributeError:
    pass

相反,IPython bases its code-completion on __dir__,因此也可以修补 gencache,这是代码生成最终发生的地方,以包含一些喜欢的东西

def __dir__(self):
    return list(set(self._prop_map_get_).union(set(self._prop_map_put_)))

到每个生成的DispatchBaseClass

【讨论】:

    【解决方案2】:

    fuglede's answer 很棒,只是想为最新版本的 IPython (7.1+) 更新它。 由于IPython.utils.generics 已从使用simplegeneric 更改为使用functools,因此@complete_object.when_type 方法应更改为@complete_object.register。所以他的初始代码应该改为:

    from IPython.utils.generics import complete_object
    import win32com.client
    
    @complete_object.register(win32com.client.DispatchBaseClass)
    def complete_dispatch_base_class(obj, prev_completions):
        try:
            ole_props = set(obj._prop_map_get_).union(set(obj._prop_map_put_))
            return list(ole_props) + prev_completions
        except AttributeError:
            pass
    

    【讨论】:

    • 我在 Spyder 的 IPython 控制台中尝试了它,它执行代码没有错误,但我没有得到代码完成。我试图启用贪婪或绝地代码完成,但没有改变。我错过了什么吗?
    猜你喜欢
    • 1970-01-01
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 2013-12-02
    相关资源
    最近更新 更多