Python, COM и проблема многопоточности - PullRequest
6 голосов
/ 03 января 2012

Я пытаюсь взглянуть на DOM IE из отдельного потока, который отправлял IE, и для некоторых свойств я получаю сообщение об ошибке «Нет поддержки такого интерфейса» Мне удалось свести проблему к этому сценарию:

import threading, time

import pythoncom
from win32com.client import Dispatch, gencache
gencache.EnsureModule('{3050F1C5-98B5-11CF-BB82-00AA00BDCE0B}', 0, 4, 0) # MSHTML

def main():
    pythoncom.CoInitializeEx(0)
    ie = Dispatch('InternetExplorer.Application')
    ie.Visible = True
    ie.Navigate('http://www.Rhodia-ecommerce.com/')
    while ie.Busy:
        time.sleep(1)

    def printframes():
        pythoncom.CoInitializeEx(0)
        document = ie.Document
        frames = document.getElementsByTagName(u'frame')
        for frame in frames:
            obj = frame.contentWindow

    thr = threading.Thread(target=printframes)
    thr.start()
    thr.join()

if __name__ == '__main__':
    thr = threading.Thread(target=main)
    thr.start()
    thr.join()

Все хорошо, пока frame.contentWindow. Тогда БАМ:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\python22\lib\threading.py", line 414, in __bootstrap
    self.run()
  File "C:\python22\lib\threading.py", line 402, in run
    apply(self.__target, self.__args, self.__kwargs)
  File "testie.py", line 42, in printframes
    obj = frame.contentWindow
  File "C:\python22\lib\site-packages\win32com\client\__init__.py", line 455, in __getattr__
    return self._ApplyTypes_(*args)
  File "C:\python22\lib\site-packages\win32com\client\__init__.py", line 446, in _ApplyTypes_
    return self._get_good_object_(
com_error: (-2147467262, 'No such interface supported', None, None)

Есть подсказка?

1 Ответ

1 голос
/ 04 января 2012

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

Вы инициализированы как многопоточная квартира - это говорит COM, что it может вызвать ваши интерфейсы в любом потоке.Он не позволяет вам вызывать другие интерфейсы в любом потоке или освобождает вас от сортировки интерфейсов, предоставляемых COM.Это будет работать только «случайно» - например, если вызываемый вами объект окажется внутрипроцессным MTA-объектом, это не имеет значения.

CoMarshalInterThreadInterfaceInStream / CoGetInterfaceAndReleaseStream делает бизнес.

Причина этого в том, что объекты могут предоставлять свои собственные прокси, которые могут быть или не быть свободными.(Или действительно предоставьте заказную сортировку).Вы должны собрать их, чтобы сказать им, что они перемещаются между нитями.Если прокси свободен, вы можете получить тот же указатель обратно.

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