来自不同线程的Pythoncom PumpMessages

我想执行类似于要求here的操作,但是使用诸如here的线程.也使用来自here的答案,我的代码可以正常工作,只是无法识别ItemAdd事件(实际上,我认为是,但是在其他线程,这就是为什么没有输出的原因).

"""Handler class that watches for incoming mails"""
import ctypes # for the WM_QUIT to stop PumpMessage()
import logging
import win32com.client
import sys
import threading
import time
import pythoncom

# outlook config
CENTRAL_MAILBOX = "My Mailbox"

# get the outlook instance and inbox folders
outlook = win32com.client.Dispatch("Outlook.Application")
marshalled_otlk = pythoncom.CoMarshalInterThreadInterfaceInStream(
    pythoncom.IID_IDispatch,outlook)


class HandlerClass(object):

    def OnItemAdd(self,item):
        logger.info("New item added in central mailbox")
        if item.Class == 43:
            logger.info("The item is an email!")


class OtlkThread(threading.Thread):

    def __init__(self,marshalled_otlk,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.marshalled_otlk = marshalled_otlk
        self.logger = logging.getLogger("OLThread")

    def run(self):
        self.logger.info("Starting up Outlook watcher\n"
                         "To terminate the program,press 'Ctrl + C'")
        pythoncom.CoInitialize()
        outlook = win32com.client.Dispatch(
            pythoncom.CoGetInterfaceAndReleaseStream(
                self.marshalled_otlk,pythoncom.IID_IDispatch
            )
        )
        user = outlook.Session.CreateRecipient(CENTRAL_MAILBOX)
        central_inbox = outlook.Session.GetSharedDefaultFolder(user,6).Items
        self.logger.info(f"{central_inbox.Count} messages in central inbox")

        win32com.client.DispatchWithEvents(central_inbox,HandlerClass)
        pythoncom.PumpMessages()
        pythoncom.CoUninitialize()  # this is prbly unnecessary as it will never be reached


def main():
    # pythoncom.CoInitialize()
    OtlkThread(marshalled_otlk,daemon=True).start()


if __name__ == "__main__":
    status = main()
    while True:
        try:
            # pythoncom.PumpWaitingMessages()
            time.sleep(1)
        except KeyboardInterrupt:
            logger.info("Terminating program..")
            ctypes.windll.user32.PostQuitMessage(0)
            sys.exit(status)

我尝试了各种方法,例如将sys.coinit_flags = 0放在顶部,如建议的here),在主线程中调用PumpWaitingMessages(),并在侧线程本身中获取Outlook应用程序,而不是传递编组的对象.这些都不起作用.

当我仅将PumpMessages放入主线程(相同的HandlerClass,但没有单独的线程)时,它就可以工作并且可以在到达时识别电子邮件,但是很明显,该线程已被阻塞,甚至无法捕获KeyboardInterrupt异常.

因此,如何使Outlook Watcher在单独的线程中运行,以将消息发送到主线程以在那里输出?

最佳答案
格式正确的问题,带有参考.谢谢.

的答案.在这种情况下,我使用“ threading.Thread(target = ….`”.但是您也可以使用继承:

import logging
import threading
import time


def task(name):
    log = logging.getLogger('task-' + name)
    log.info("Starting up Outlook watcher\n"
                     "To terminate the program,press 'Ctrl + C'")
    while True:
        log.info("Doing work that takes time")
        time.sleep(1)


class OtlkThread(threading.Thread):

    def __init__(self,**kwargs):
        self.log = logging.getLogger('task-class')
        super().__init__(*args,**kwargs)

    def run(self):
        self.log.info("Starting up Outlook watcher\n"
                 "To terminate the program,press 'Ctrl + C'")
        while True:
            self.log.info("Doing work that takes time")
            time.sleep(1)

def main():
    t1 = threading.Thread(target=task,args=('daemon',),daemon=True)
    t1.start()
    t2 = OtlkThread()
    t2.start()


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG,)

    main()
    while True:
        time.sleep(1)

相关文章

Python中的函数(二) 在上一篇文章中提到了Python中函数的定...
Python中的字符串 可能大多数人在学习C语言的时候,最先接触...
Python 面向对象编程(一) 虽然Python是解释性语言,但是它...
Python面向对象编程(二) 在前面一篇文章中谈到了类的基本定...
Python中的函数(一) 接触过C语言的朋友对函数这个词肯定非...
在windows下如何快速搭建web.py开发框架 用Python进行web开发...