python信號處理:優(yōu)雅地終止父進程及其子進程
在Python多進程編程中,使用信號終止父進程后,子進程可能持續(xù)運行,這通常需要更精細的進程管理策略。本文探討此問題并提供解決方案。
問題描述
假設a.py創(chuàng)建了一個父進程和一個子進程,父進程ID寫入文件。b.py讀取此ID并發(fā)送終止信號(SIGTERM)。然而,父進程終止后,子進程可能繼續(xù)運行。
以下為示例代碼(與原文略有不同,更簡潔易懂,并修復了原代碼中的錯誤):
a.py:
立即學習“Python免費學習筆記(深入)”;
import multiprocessing import os import signal import time def child_process(): while True: print("子進程運行中...") time.sleep(1) if __name__ == "__main__": child = multiprocessing.Process(target=child_process) child.start() with open("pidfile.txt", "w") as f: f.write(str(os.getpid())) child.join() # 等待子進程結束 print("父進程結束")
b.py:
import os import signal try: with open("pidfile.txt", "r") as f: pid = int(f.read()) os.kill(pid, signal.SIGTERM) print(f"已向進程 {pid} 發(fā)送 SIGTERM 信號") except FileNotFoundError: print("pidfile.txt 未找到") except Exception as e: print(f"發(fā)生錯誤: {e}")
解決方案:利用進程組
解決此問題關鍵在于理解進程組的概念。父進程及其子進程屬于同一個進程組。通過向進程組發(fā)送信號,可以確保所有進程都接收到信號。
改進后的代碼:
a.py:
立即學習“Python免費學習筆記(深入)”;
import multiprocessing import os import signal import time def child_process(): while True: print("子進程運行中...") time.sleep(1) if __name__ == "__main__": child = multiprocessing.Process(target=child_process) child.start() pgid = os.getpgid(0) # 獲取當前進程組ID with open("pidfile.txt", "w") as f: f.write(str(pgid)) child.join() print("父進程結束")
b.py:
import os import signal try: with open("pidfile.txt", "r") as f: pgid = int(f.read()) os.killpg(pgid, signal.SIGTERM) # 向進程組發(fā)送信號 print(f"已向進程組 {pgid} 發(fā)送 SIGTERM 信號") except FileNotFoundError: print("pidfile.txt 未找到") except Exception as e: print(f"發(fā)生錯誤: {e}")
通過使用os.getpgid(0)獲取進程組ID,并將進程組ID寫入文件,b.py使用os.killpg()向整個進程組發(fā)送SIGTERM信號,確保父進程和子進程都被干凈地終止。 此外,a.py中的child.join()確保父進程等待子進程結束后才退出,避免了競態(tài)條件。 最后,代碼也進行了更健壯的異常處理。
這個改進后的方案更可靠,避免了原代碼中可能存在的潛在問題,并提供了更清晰的代碼結構。
? 版權聲明
文章版權歸作者所有,未經(jīng)允許請勿轉載。
THE END