python - 如何让子线程处理Python中的主进程被杀死或关键中断?

标签 python multithreading

在多线程设计中,我想在程序异常退出时做一些干净的步骤。正在运行的线程应该清理当前任务然后退出,而不是立即被杀死并留下一些脏数据。我发现使用 threading模块无法捕获 KeyInterrupt异常(exception)。

这是我的测试代码:

#!/usr/bin/env python3

from time import sleep

def do_sth():
    print("I'm doing something...")
    sleep(10)

if __name__ == "__main__":
    do_sth()

Python 将引发 KeyInterruptCTRL-c 时出现异常
$ Python3 test.py
I'm doing something ... 
^C
Traceback (most recent call last):
File "test.py", line 10, in <module>
do_sth ()
File "test.py", line 7, in do_sth
sleep (10)
KeyboardInterrupt

所以我可以捕捉到这个异常。
def do_sth ():
    try:
        print ("I'm doing something ...")
        sleep (10)
    except (KeyboardInterrupt, SystemExit):
        print ("I'm doing some clean steps and exit.")

但是当我使用线程模块时,根本不会引发这个异常。
#!/usr/bin/env python3

from time import sleep
import threading

def do_sth():
    print("I'm doing something...")
    sleep(10)

if __name__ == '__main__':
    t = threading.Thread(target=do_sth)
    t.start()
    t.join()

结果:
$ python3 test.py
I'm doing something...
^C

正在运行的线程已经被直接杀死,没有引发异常。

我该如何处理?

最佳答案

一种方法是处理 KeyboardInterrupt 异常。

在这种情况下要做的另一件事是跨所有线程管理应用程序的状态。
解决方案之一是添加对 Signals 的支持。在你的代码中。它允许优雅地处理您的进程的关闭。

这是一个简单的设置:

class SignalHandler:
    continue_running = True

    def __init__(self):
        signal.signal(signal.SIGUSR2, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
        signal.signal(signal.SIGINT, self.signal_handler)
        logging.info("SignalHandler::Init")

    def signal_handler(self, num, stack):
        logging.warning('Received signal %d in %s' % (num, threading.currentThread()))
        SignalHandler.continue_running = False
        logging.warning("Time to SHUT DOWN ALL MODULES")

所有线程都会尝试并利用来自 SignalHandler.continue_running 的状态。以确保他们都知道何时停止。
如果有人试图通过调用 kill -2 [PID] 来杀死这个 python 进程例如 - 所有线程都会知道需要关闭。

关于python - 如何让子线程处理Python中的主进程被杀死或关键中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30684531/

相关文章:

java - 如何在 netbeans 中同时调试多个线程/runnable

c++ - 为什么冗余的额外作用域 block 会影响 std::lock_guard 行为?

java - 关于同步方法、锁和监视器的说明

python - python for循环中追加函数的机制

python - 格式化函数中的字符串

python - 缺少 key 的 Pandas groupby

java - 为什么在屏障操作执行后无法立即获取 cyclingBarrier?

java - "AWT-EventQueue-0"java.lang.NullPointerException 异常

python - Pygame 相机跟随 2d 平铺游戏

python - 如何解决 sns.pairplot 错误 Selected KDE bandwidth is 0. Cannot estimate density”?