Python、COM与多线程问题
我正在尝试从一个单独的线程查看IE的DOM(文档对象模型),但是在访问某些属性时遇到了“没有这样的接口支持”的错误。我把问题简化成了下面这个脚本:
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
正确的做法是手动处理这些东西。这不是一个变通办法,而是你应该这样做。你其实不需要使用公寓线程。
你初始化的时候选择了多线程公寓,这告诉COM(组件对象模型)它可以在任何线程上调用你的接口。但这并不意味着你可以在任何线程上调用其他接口,也不能免除你对COM提供的接口进行处理的责任。这样做可能只会“偶然”成功,比如如果你调用的对象恰好是一个进程内的MTA对象,那就没关系了。
CoMarshalInterThreadInterfaceInStream
和CoGetInterfaceAndReleaseStream
是处理这个问题的工具。
这样做的原因是,对象可以提供自己的代理,这些代理可能是自由线程的,也可能不是。(或者确实提供自定义的处理方式)。你需要进行处理,以告诉它们正在不同的线程之间移动。如果代理是自由线程的,你可能会得到同一个指针。