Импорт pywinauto (или comtypes) уничтожает существующий COM-объект

Создание / получение COM-объекта с использованием win32com.client.GetActiveObject, а затем import pywintypes приводит к AttributeError при каждом вызове исходного COM-объекта.

Код для воспроизведения

import win32com.client
catia_com = win32com.client.GetActiveObject('CATIA.Application')

# then later when needed, do some pywinauto stuff
import pywinauto.application

# back to working directly on catia com object
print(catia.caption)  # raises Attribute error from within win32com.client

Почему это происходит и как это исправить?


person hansonap    schedule 13.09.2018    source источник


Ответы (1)


Мне удалось найти решение этой проблемы, которым я хотел бы поделиться, но я также хотел бы услышать отзывы о моем понимании и о том, какова соответствующая зависимость, где это следует решать, чтобы не допустить возникновения такой же проблемы у других.

Решение

Добавьте import comtypes перед вызовом win32com.client.

Пример

import comtypes
import win32com.client
catia_com = win32com.client.GetActiveObject('CATIA.Application')

# then later when needed, do some pywinauto stuff
import pywinauto.application

# back to working directly on catia com object
print(catia.caption)  # it works!

Причина и объяснение (насколько я мог определить)

TL; DR

import comtypes вызывает CoInitializeEx с флагом COINIT_MULTITHREADED, который перекрывает режим, установленный win32com.client.GetActiveObject.

Полное объяснение

Я пришел к такому выводу, потому что, комментируя pythoncom.CoUninitialize() (я беспокоился, что это убивает COM-объект, возвращенный из win32com.client.GetActiveObject) в pywinauto.__init__ и повторно запуская код, из comtypes.__init__ возникла следующая ошибка:

OSError: [WinError -2147417850] Cannot change thread mode after it is set

Я знаю, что comtypes.__init__ обрабатывает выбор флагов по умолчанию для CoInitializeEx и не может определить, какова win32com lib, но полагает, что он также, вероятно, проверяет существующие флаги, поэтому я добавил import comtypes.

Где я все еще нечеткий

  1. Как определить флаги модели параллелизма для win32com?
  2. Как указать флаги модели параллелизма при вызове win32com.client.GetActiveObject?
  3. Почему именно это решение работает ... вызов pythoncom.CoInitializeEx(0x0) прямо перед вызовом win32com.client.GetActiveObject не работает!

Если я смогу получить ответ на вышеуказанный вопрос, я могу порекомендовать win32com установить sys.coinit_flags (это то место, где проверяется comtypes.__init__).

Ресурсы

person hansonap    schedule 13.09.2018