如何在Python中以独立线程启动win32应用程序
因此,我有以下代码段试图通过win32api启动Microsoft Powerpoint:如何在Python中以独立线程启动win32应用程序,python,winapi,pywin32,python-multithreading,win32com,Python,Winapi,Pywin32,Python Multithreading,Win32com,因此,我有以下代码段试图通过win32api启动Microsoft Powerpoint: import threading import win32com.client import sys class myDemo(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): try: myObject =
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在单独的线程上异步运行,我应该如何解决
提前谢谢
编辑:显然我的问题与此有关:
然而,除了建议的正确解决方案之外,似乎没有人能回答COM为什么会这样做。好的,所以我想我找到了答案,但我还不确定它为什么会起作用 如果我从发送microsoft powerpoint的try块内的页面顶部剪切并粘贴此行
import win32com.client
,则应用程序将成功运行
然而,我仍然不知道为什么。由于COM和线程技术的复杂性以及它们为何以这种方式工作,恐怕您的问题不能用一两句话来概括。但对于初学者来说,这里有一些很好的信息,说明COM在线程下的行为方式:
http://msdn.microsoft.com/en-us/library/ms809971.aspx
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()
此外,您还应该考虑在Win32 中查看<强> Python编程。它包含了一些有用的信息,可以更清楚地了解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线程称为多线程单元线程:
http://msdn.microsoft.com/en-us/library/ms809971.aspx
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()
希望这能有所帮助。至少还有两种方法可以解决这个问题:
run()
方法代替start()
,即test.run()
import pythoncom;CoInitialize()
请注意,使用run()而不是start()已经在其他脚本中进行了测试,并且对我来说一直都很有效 “开始”是什么意思?您的对象只有一种方法,“run”start()异步执行对象的run方法。您可能会感到困惑,因为在导入
pythoncom
之前必须使用sys.coinit\u flags=0
。pythoncom模块在导入期间调用CoInitialize()
。它会查找sys.coinit_flags以查看开发人员是否需要不同的东西。谢谢。非常有帮助!但是在第一段代码中,我认为应该是:pythoncom.CoInitialize()&pythoncom.CoUninitialize(),而不是win32com.CoInitialize()&win32com.CoUninitialize()