在Python中創建一個守護進程已經有很多問題,比如this one,它很好地回答了這個問題。
那麼,你如何讓你的守護進程做後臺工作?
如您所懷疑的,線程是一個明顯的答案。但是有三種可能的複雜性。
首先,有關機。如果你幸運的話,你的功能可以在任何時候立即被殺死,沒有損壞的數據或(太重要的)失去工作。在這種情況下:
def worker():
while True:
crunchData()
# ... somewhere in the daemon startup code ...
t = threading.Thread(target=worker)
t.daemon = True
t.start()
請注意t.daemon
。 A "daemon thread"與你的程序是一個守護進程無關;這意味着你可以退出主流程,它會被立即殺死。
但是如果crunchData
不能被殺死呢?然後,你需要做這樣的事情:
quitflag = False
quitlock = threading.Lock()
def worker():
while True:
with quitlock:
if quitflag:
return
crunchData()
# ... somewhere in the daemon startup code ...
t = threading.Thread(target=worker)
t.start()
# ... somewhere in the daemon shutdown code ...
with quitlock:
quitflag = True
t.join()
我假設的crunchData
每個迭代認爲並不需要很長時間。如果是這樣,您可能需要定期在功能本身內檢查quitFlag
。
同時,您希望您的請求處理程序訪問後臺線程正在生成的一些數據。你也需要一些同步。
顯而易見的是隻使用另一個Lock
。但是很有可能的是crunchData
正在頻繁地寫入數據。如果它一次持有鎖定10秒,則請求處理程序可能會阻塞10秒。但是,如果它抓住並釋放鎖定一百萬次,那可能比實際工作需要更長的時間。
一種替代方法是對您的數據進行雙緩衝:將crunchData
寫入新副本,然後在完成後,暫時取鎖並設置currentData = newData
。
根據您的使用情況,Queue
,文件或其他可能更簡單。
最後,crunchData
大概是做了大量的CPU工作。您需要確保請求處理程序的CPU工作量非常小,或者每個請求都會減慢速度,因爲兩個線程都在GIL上進行爭奪。通常這是沒有問題的。如果是,請使用multiprocessing.Process
而不是Thread
(這會使兩個進程之間的數據共享或傳遞稍微複雜一些,但仍然不算太差)。
您使用的是Linux嗎? – Homer6
我建議使用supervisord - 它避免了處理守護進程問題的需要。 – Marcin
這裏有兩個單獨的問題。首先,「我該如何做兩件事」,是的,使用後臺線程是一種明顯的方式,並且可以工作。然後,有「如何在Python中編寫守護進程」,這是一個重複。所以,我會忽略第二個。 – abarnert