Каков правильный тип подсказки для COM-объектов в python? - PullRequest
3 голосов
/ 19 февраля 2020

Я использую COM-объекты в python для предоставления программируемых интерфейсов стороннему программному обеспечению. Это достигается с помощью Dispatch из win32com.client. В моем проекте также использовалась подсказка типа из python .3.7, однако я не уверен, как бы вы определили тип этих COM-объектов для целей подсказки типа. Этот вопрос относится ко всем имеющимся у меня COM-объектам, реальным примером является набор записей Microsoft Direct X: 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.

Моей первой мыслью было просто вызвать 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[], однако я не уверен, есть ли более питонная / лучшая альтернатива.

Спасибо

1 Ответ

2 голосов
/ 20 февраля 2020

Боюсь, что вы, к сожалению, сталкиваетесь с одним из ограничений ввода Python. В частности:

  1. Насколько я знаю, нет заглушек типов для библиотеки pywin32 в Typeshed или в стороннем модуле. Это означает, что не существует существующей канонической ссылки на то, каким должен быть этот тип.
  2. Динамическая диспетчеризация на произвольные объекты приведет к ограничению возможных значений до express с использованием только подсказок типа (при условии, что Dispatch действительно отправляет произвольные объекты).

Итак, я рекомендую один из следующих трех подходов:

  1. Если вы хотите абсолютно ничего не предполагать о возвращаемом введите и обработайте его как просто непрозрачный BLOB-объект; тип возвращаемого значения будет object. Это наиболее строгий и безопасный тип, поскольку совместимый с PEP 484 механизм проверки типов позволяет вызывающей стороне использовать только методы, присутствующие во всех Python объектах, таких как __str__ или __eq__.

  2. Если вы хотите абсолютно ничего не предполагать в отношении возвращаемого типа, но также не накладывать никаких ограничений на его использование, укажите тип возвращаемого значения Любой , тип Dynami c. Это наиболее допустимая и небезопасная операция: вы говорите, что вывод имеет какой-то динамический тип c, и говорите контролеру типов, чтобы позволить вызывающей стороне использовать возвращаемый объект, как им угодно.

    Это опция по умолчанию ", так сказать: поскольку для pywin32 нет доступных заглушек типов, средство проверки типов вернется к предположению, что Dispatch(...) имеет тип возврата Any.

  3. Если вы знаете для Если в возвращаемом типе всегда будут указаны определенные c доступные методы или атрибуты, у вас будет возвращаемый тип: Protocol . Протоколы в основном позволяют вам делать структурный подтип : любой класс, который реализует методы и атрибуты протокола, считается подтипом этого протокола, даже если класс никак не наследуется от протокола. Протоколы в основном похожи на Go интерфейсы, если вы знакомы с Go.

    Вы можете создать здесь выделенную функцию create_adodb_recordset(...), чтобы вы могли более полно настроить тип возвращаемого значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...