2012-01-03 109 views
6

我试图从IE调用IE的单独线程来看看IE的DOM,对于一些属性我得到一个“没有这样的接口支持”的错误。我设法降低问题这个脚本:python,COM和多线程问题

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。然后bam:

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

正交于您的问题:更新到Python2.7;尝试[硒](http://selenium.googlecode.com/svn/trunk/docs/api/py/index.html) – jfs 2012-01-03 18:47:16

+0

现在不是一个选项;我处于商业环境中,而且我们的工作远远超过了Selenium。尽管我们正在升级Python的方法:)我们通过使用公寓而不是免费的线程和编组东西来找到解决方法,但我仍然好奇。 – fraca7 2012-01-04 07:59:25

回答

1

正确的答案是手动编组东西。这不是一个解决方法,这是你应该在这里做的。你不应该使用公寓线程。

你初始化为多线程单元 - 告诉COM该可以调用你的接口在任何线程。它不会而不是允许你调用任何线程上的其他接口,或者原谅你从COM提供的编组接口。这只会“偶然”发生 - 例如如果您所调用的对象恰好是一个进程内MTA对象,则无关紧要。

CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream做生意。

这样做的原因是对象可以提供自己的代理,这些代理可以是也可以不是自由线程的。 (或者确实提供自定义编组)。你必须编组他们,告诉他们他们正在线程之间移动。如果代理是自由线程的,则可能会返回相同的指针。