如何在Python中以独立线程启动win32应用程序

如何在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 =

因此,我有以下代码段试图通过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 = 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()

  • 在myObject=win32com.client.Dispatch(“Powerpoint.Application”)之前插入以下行:
    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()