因此,下面的代码片段试图通过win32api启动:
import threading
import win32com.client
import sys
class myDemo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
try:
myObject = win32com.client.Dispatch("Powerpoint.Application")
print "OK"
except:
print "Failed to start Powerpoint!"
sys.exit(1)
print "Now attempting to shutdown..."
try:
myObject.quit()
except:
print "Error"
if __name__ == "__main__":
test = myDemo()
test.start()
问题是它失败了,我不知道原因。但是,如果我将最后一行更改为test.run()
,它将成功启动。那么,为什么test.start()
失败了?
为什么会发生这种情况?考虑到我需要Powerpoint来异步地在独立线程上运行,我应该如何解决它?
提前谢谢。
编辑:显然我的问题与此有关:http://python.6.x6.nabble.com/Dispatch-error-CoInitialize-has-not-been-called-td1951088.html
然而,除了提出正确的解决方案之外,似乎没有人回答COM为什么会这样做。
发布于 2014-03-24 19:41:08
恐怕你的问题不能用一两句话来概括,因为COM和线程的复杂性,以及它们为什么会以这样的方式工作。但首先,这里有一些很好的信息,说明了为什么COM在线程下的行为方式:
http://msdn.microsoft.com/en-us/library/ms809971.aspx
此外,您应该考虑阅读Python编程on Win32一书。它包含了更多关于COM线程的有用信息。(尽管它已经问世,但它仍然是有用的。)
最后,如果从您提供的引用中看不清楚,每当您的程序使用线程和COM时,您必须在代码中指示您将在线程中使用COM:
import pythoncom
import win32com.client
### ... inside the thread function ...
x = win32com.client.Dispatch("someCOMobject")
win32com.CoInitialize()
# com calls here
win32com.CoUninitialize()
这种类型的调用使用的是所谓的单公寓线程。它发生在线程代码本身实例化COM对象时。
如果您发现自己在线程代码之外实例化单个COM对象(并且在线程代码中使用实例化对象,例如在线程之间传递对COM对象的访问),那么这种类型的COM线程被称为多线程公寓线程:
import sys
sys.coinit_flags = 0
import pythoncom
import win32com.client
# ... outside the thread function ...
x = win32com.client.Dispatch("someCOMobject")
# ... inside the thread function ...
pythoncom.CoInitialize(pythoncom.COINIT_MULTITHREADED)
# com calls here for x
pythoncom.CoUninitialize()
希望这能有所帮助。
发布于 2014-01-15 15:42:11
好的,所以我想我找到了一个答案,但我还不知道为什么会起作用。
如果我从页面顶部剪切并粘贴这一行import win32com.client
,就在我发送microsoft的try块中,应用程序就会成功运行。
不过,我还是找不出原因。
发布于 2018-02-04 14:41:28
至少还有两种方法可以解决这个问题:
run()
方法而不是start()
,即test.run()
myObject = win32com.client.Dispatch("Powerpoint.Application")
之前插入以下行:import pythoncom; CoInitialize()
注意,使用run()而不是start()已经在其他脚本中进行了测试,它对我总是有效的!
https://stackoverflow.com/questions/21141217
复制相似问题