我想执行类似于要求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在单独的线程中运行,以将消息发送到主线程以在那里输出?
最佳答案
格式正确的问题,带有参考.谢谢.
原文链接:/python/533148.html的答案.在这种情况下,我使用“ 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)