Python中用于COM对象的正确类型提示是什么?

5

我正在使用Python中的COM对象,使用win32com.client中的Dispatch来向第三方软件公开可编程接口。我的项目还利用了Python 3.7的类型提示,但我不确定为了类型提示如何定义这些COM对象的类型。这个问题涉及到我所有的COM对象,一个真实的例子是Microsoft Direct X Recordset:Dispatch("ADODB.Recordset")

from win32com.client import Dispatch
def create_my_com_object_instance(input_arg: Dict[str, Union[str, float, int]]) -> <type_of_com_object_here>:
    my_instance = Dispatch("ADODB.Recordset")
    # Set attributes/call methods of this instance here ... 
    return my_instance

在上面的代码片段中,我会将'type_of_com_object_here'替换为COM对象类型。
我的第一个想法是在实例上调用type()并使用返回的类型:
x = Dispatch("ADODB.Recordset")
x
Out[1]: <win32com.gen_py.Microsoft ActiveX Data Objects 6.1 Library._Recordset instance at 0x83848456>
type(x)
Out[2]: win32com.gen_py.B691E011-1797-432E-907A-4D8C69339129x0x6x1._Recordset._Recordset
x.__class__
Out[3]: win32com.gen_py.B691E011-1797-432E-907A-4D8C69339129x0x6x1._Recordset._Recordset

这个方法不能返回适合定义COM对象的类型。我认为可以使用TypeVar('T')Generic[]创建一个抽象基类,但是我不确定是否有更好的Pythonic方法。

谢谢

1个回答

4
很抱歉,您可能遇到了Python输入的限制之一。特别是:
  1. 据我所知,在Typeshed或作为第三方模块中没有pywin32库的类型存根。这意味着没有现有的规范参考该类型应该是什么。
  2. 动态分派到任意对象将会超出仅使用类型提示表达的可能性的限制(假设Dispatch确实分派到任意对象)。
因此,我建议采取以下三种方法之一:
  1. 如果你希望对返回类型一无所知,只将其视为不透明的二进制块,则返回类型应为object。这是最严格和类型安全的选项,因为符合PEP 484的类型检查器只允许调用方使用所有Python对象中存在的方法,例如__str____eq__

  2. 如果你希望对返回类型一无所知,但同时又不对其使用施加任何限制,则返回类型应为Any,即动态类型。这是最宽松和不安全的操作:你在说输出是某个动态类型,并告诉类型检查器让调用者随心所欲地使用返回的对象。

    这是“默认选项”,因为pywin32没有类型存根可用,类型检查器会退而求其次,假定Dispatch(...)的返回类型为Any。

  3. 如果你确定返回类型始终具有某些特定的方法或属性可用,则返回类型应为Protocol。协议基本上让你做结构子类型:任何实现协议方法和属性的类都被视为该协议的子类型,即使该类没有以任何方式继承该协议。如果你熟悉Go语言,协议基本上就像Go的接口。

    你可能希望在这里创建一个专用的create_adodb_recordset(...)函数,以便更充分地自定义返回类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接