如何在Python中的不同线程中启动win32应用程序

2024-09-29 00:19:45 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我有以下代码片段,它试图通过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在一个独立的线程上异步运行,我应该如何解决它?在

提前谢谢。在

编辑:显然我的问题与此有关:http://python.6.x6.nabble.com/Dispatch-error-CoInitialize-has-not-been-called-td1951088.html

然而,除了提出的正确的解决方案之外,似乎没有人能够回答COM为什么会这样。在


Tags: runtestimportselfclientinitdefsys
3条回答

由于COM和线程的复杂性以及它们为什么会这样工作,恐怕你的问题不能用一两句话来概括。但对于初学者来说,以下是一些很好的信息,说明COM在线程环境下的行为方式:

http://msdn.microsoft.com/en-us/library/ms809971.aspx

此外,您应该考虑阅读《在Win32上进行Python编程》一书。它包含了一些有用的信息,可以帮助我们更好地理解COM线程。(尽管年代久远,它仍然有用。)

最后,如果从您提供的引用中看不清楚,每当您的程序使用线程和COM时,您必须在代码中指明您将在线程中使用COM:

^{pr2}$

这种类型的调用使用所谓的单单元线程。当线程代码本身实例化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()

希望这有帮助。在

好吧,我想我找到了一个答案,但我还不确定它为什么有用。。在

如果我从页面顶部剪切并粘贴这一行import win32com.client就在我分发microsoft powerpoint的try块内,则应用程序成功运行。在

但是,我还是不知道为什么。在

至少还有两种方法可以解决这个问题:

  1. 使用run()方法代替start(),即test.run()

  2. myObject = win32com.client.Dispatch("Powerpoint.Application")之前插入以下行:import pythoncom; CoInitialize()

请注意,使用run()代替start()已经在其他脚本中进行了测试,而且它始终对我有效!在

相关问题 更多 >