使用win32com和多线程

ste*_*nci 13 python multithreading win32com python-3.x

我正在使用CherryPy开发一个需要通过COM访问一些应用程序的Web应用程序.

现在我用每个请求创建一个新的应用程序实例,这意味着每个请求等待3秒钟启动应用程序,0.01等待实际作业.

我想启动每个COM应用程序一次并使其保持活动状态并在以下请求中重复使用它几秒钟,因为大多数时候它被5-10个ajax请求的突发使用,然后几个小时都没有.

是否可以在CherryPy应用程序的所有线程之间共享COM abject?

以下是一些实验的摘要,这些实验显示了它现在如何处理每个请求以及它如何在线程之间不起作用.

以下代码成功启动和停止Excel:

>>> import pythoncom, win32com.client
>>> def start():
    global xl
    xl = win32com.client.Dispatch('Excel.Application')

>>> def stop():
    global xl
    xl.quit()
    xl = None

>>> start()
>>> stop()
Run Code Online (Sandbox Code Playgroud)

但是下面的代码启动Excel并在3秒后关闭它.

>>> import pythoncom, win32com.client, threading, time
>>> def start():
    global xl
    pythoncom.CoInitialize()
    xl = win32com.client.Dispatch('Excel.Application')
    time.sleep(3)

>>> threading.Thread(target=start).start()
Run Code Online (Sandbox Code Playgroud)

我添加了调用,CoInitialize()否则xl对象将无法工作(请参阅此文章).

我添加了3秒的暂停,所以我可以在任务管理器上看到EXCEL.EXE进程启动并且活着3秒钟.

为什么它在启动它的线程结束后死亡?

我检查了文档CoInitialize(),但我无法理解是否有可能让它在多线程环境中工作.

Mar*_*mro 20

如果你想在多个线程中使用win32com,你需要做更多的工作,因为COMObject无法直接传递给线程.您需要使用CoMarshalInterThreadInterfaceInStream()CoGetInterfaceAndReleaseStream()在线程之间传递实例:

import pythoncom, win32com.client, threading, time

def start():
    # Initialize
    pythoncom.CoInitialize()

    # Get instance
    xl = win32com.client.Dispatch('Excel.Application')

    # Create id
    xl_id = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, xl)

    # Pass the id to the new thread
    thread = threading.Thread(target=run_in_thread, kwargs={'xl_id': xl_id})
    thread.start()

    # Wait for child to finish
    thread.join()

def run_in_thread(xl_id):
    # Initialize
    pythoncom.CoInitialize()

    # Get instance from the id
    xl = win32com.client.Dispatch(
            pythoncom.CoGetInterfaceAndReleaseStream(xl_id, pythoncom.IID_IDispatch)
    )
    time.sleep(5)


if __name__ == '__main__':
    start()
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅:https://mail.python.org/pipermail/python-win32/2008-June/007788.html