假設我有一些消費者守護執行緒,只要主執行緒將物件放在佇列中,它們就會不斷地從佇列中獲取物件,并對它們執行一些長時間的操作(幾秒鐘)。
問題是,每當主執行緒完成時,守護執行緒在完成處理佇列中剩余的任何內容之前都會被殺死。
我知道解決此問題的一種方法可能是等待守護執行緒完成處理佇列中剩余的任何內容然后退出,但我很好奇是否有任何方法可以讓守護執行緒自行“清理”(即完成處理佇列中剩余的任何內容)當主執行緒退出時,沒有明確地讓主執行緒告訴守護執行緒開始清理。
這背后的動機是我制作了一個 python 包,它有一個日志處理程式類,當用戶嘗試記錄某些內容(例如使用logging.info("message"))時,它會將專案放入佇列中,并且處理程式有一個通過網路發送日志的守護執行緒。如果守護執行緒可以自行清理,我更愿意,這樣包的用戶就不必手動確保讓他們的主執行緒等待日志處理程式完成其處理。
最小的作業示例
# this code is in my package
class MyHandler(logging.Handler):
def __init__(self, level):
super().__init__(level=level)
self.queue = Queue()
self.thread = Thread(target=self.consume, daemon=True)
self.thread.start()
def emit(self, record):
# This gets called whenever the user does logging.info, or similar
self.queue.put(record)
def consume(self):
while True:
record = self.queue.get()
send(record) # send record over network, can take a few seconds (assume it never raises)
self.queue.task_done()
# This is user's main code
# user will have to keep a reference to the handler for later. I want to avoid this.
my_handler = MyHandler()
# set up logging
logging.basicConfig(..., handlers=[..., my_handler])
# do some stuff...
logging.info("this will be sent over network")
# some more stuff...
logging.error("also sent over network")
# even more stuff
# before exiting must wait for handler to finish sending
# I don't want user to have to do this
my_hanler.queue.join()
uj5u.com熱心網友回復:
您可以使用threading.main_thread.join()which 將等到關閉,如下所示:
import threading
import logging
import queue
class MyHandler(logging.Handler):
def __init__(self, level):
super().__init__(level=level)
self.queue = queue.Queue()
self.thread = threading.Thread(target=self.consume) # Not daemon
# Shutdown thread
threading.Thread(
target=lambda: threading.main_thread().join() or self.queue.put(None)
).start()
self.thread.start()
def emit(self, record):
# This gets called whenever the user does logging.info, or similar
self.queue.put(record)
def consume(self):
while True:
record = self.queue.get()
if record is None:
print("cleaning")
return # Cleanup
print(record) # send record over network, can take a few seconds (assume it never raises)
self.queue.task_done()
快速測驗代碼:
logging.getLogger().setLevel(logging.INFO)
logging.getLogger().addHandler(MyHandler(logging.INFO))
logging.info("Hello")
exit()
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/412298.html
標籤:
