【问题标题】:Python Multiprocessing: What is the better implementation to terminate daemon process when the parent process terminated?Python Multiprocessing:当父进程终止时终止守护进程的更好实现是什么?
【发布时间】:2023-05-11 12:50:01
【问题描述】:

我在 Ubuntu 上的 Python 3.6 上使用多处理来处理与另一台设备的更快通信。

我设置daemon = True 在父进程完成时终止子进程。但是,当主进程终止时,另一个进程(以下代码中的_another_process)有时不会终止并继续存在。然后,当我再次运行相同的程序时,运行上述代码时出现address already in use 错误。当然,我可以杀死这个进程,但这很烦人,我想解决。

Class Xxx
 def __init__(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.settimeout(2.5)
        self.sock.bind((self.ip, self.port))
        self.sock.settimeout(None)    
        self.start_process()
        time.sleep(1.5)

    def start_process(self):      
        p = mp.Process(target=self._another_process)
        time.sleep(1)
        p.daemon = True
        p.start()

    def _another_process(self):
        while True:
            # Do continuous (infinite) operation

我不知道为什么有时会终止而有时不会,但是有没有更好的实现来实现我想要的?或者,daemon = True 是最好的方法吗?

我认为我不应该使用join(),因为我的子进程有无限操作,但如果我误解了,请告诉我。

【问题讨论】:

  • 谢谢。我已经有两个解决方案,但不确定哪个更好。使用 SO_REUSEADDR 安全吗?终止进程时是否调用主析构函数?

标签: python linux multiprocessing


【解决方案1】:

来自 python3 文档,在 main 的析构函数中 process.terminate():

p.start() print(p, p.is_alive()) p.terminate()

这将发送 SIGTERM 以由子进程处理。 或者,使用p.kill() 发送 SIGKILL。

https://docs.python.org/3/library/multiprocessing.html 上的完整示例

关于如何在您的应用程序中处理 SIGTERM: How to process SIGTERM signal gracefully?

【讨论】:

  • 谢谢。我会用这个。使用它有任何缺点或潜在问题吗?
  • 你应该知道它不会强制子进程终止,而是发送可以被子进程捕获、忽略或以任何方式处理的 unix 信号 SIGTERM。
  • 我创建了析构函数(我将 p 替换为 self.process)并运行 terminate(),但它仍然运行。 print(self.process, self.process.is_alive()) 的结果是 <Process(Process-1), started daemon)>
  • 我建议 SIGKILL 不能被捕获 - 而不是 terminate() 使用 kill() 或以其他方式捕获子进程中的 SIGTERM 并优雅退出。 *.com/questions/18499497/…
  • 谢谢。我尝试使用优雅退出,但每当调用 SIGTERM 时,子进程都会暂停其进程,因此无法使用标志优雅退出。
【解决方案2】:

要解决“地址已被使用”的问题,请尝试添加 SO_REUSEADDR 套接字选项。

【讨论】: