我在 python 中使用 COM 对象来向 3rd 方软件公开可编程接口。这是通过使用
Dispatch
from
win32com.client
来实现的。我的项目也一直在使用 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
在上面的代码片段中,我将用 COM 对象类型替换 'type_of_com_object_here'。
My第一个想法是在实例上调用
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/更好的替代方案可用。
谢谢
虽然可以使用
TypeVar
和
Generic
来创建包装类型提示,但对于 COM 对象来说,这可能变得复杂且麻烦。 这是因为
win32com
为每个 COM 对象动态生成包装器类,这些类通常不是以直接方式继承的。
实用方法:
对于 COM 对象的类型提示,最实用且最不易出错的方法是使用
object
或
Any
。这不会提供特定的类型信息,但会让 MyPy 和其他类型检查器知道它是一个对象,你可以调用属性和方法,而不会产生错误。
from typing import Any
def create_my_com_object_instance(input_arg: dict[str, str | float | int]) -> Any:
my_instance = Dispatch("ADODB.Recordset")
# ...
return my_instance
优点:
- 简单: 不需要复杂的类型定义。
-
兼容性:
与
win32com
的动态特性很好地配合。
缺点:
- 没有类型安全: 你会失去 COM 对象的类型检查优势。
其他选择:
-
Protocol(协议): 如果需要更严格的类型检查,并且你正在与多个 COM 对象交互,则可以定义一个
Protocol
来描述常用方法和属性。但是,这需要更多工作,并且可能无法涵盖所有情况。 -
存根文件: 为生成的
win32com
包装器创建存根文件 (*.pyi
) 可以提供更精确的类型信息。但这需要深入了解win32com
的内部工作原理,并且可能难以维护。
总的来说,对于大多数情况,使用
object
或
Any
是最实用的方法。如果需要更强的类型安全,请考虑使用 Protocol 或存根文件,但要权衡所涉及的复杂性和维护成本。