【问题标题】:Python SIGINT not caughtPython SIGINT 未捕获
【发布时间】:2015-04-15 21:01:20
【问题描述】:

我不明白为什么我的 SIGINT 从未被下面的代码捕获。

#!/usr/bin/env python
from threading import Thread
from time import sleep
import signal

class MyThread(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.running = True

    def stop(self):
        self.running = False

    def run(self):
        while self.running:
            for i in range(500):
                col = i**i
                print col
                sleep(0.01)

global threads
threads = []

for w in range(150):
    threads.append(MyThread())

def stop(s, f):
    for t in threads:
        t.stop()

signal.signal(signal.SIGINT, stop)

for t in threads:
    t.start()

for t in threads:
    t.join()

要清理此代码,我宁愿尝试/排除join() 并在出现异常时关闭所有线程,这样行吗?

【问题讨论】:

标签: python multithreading sigint


【解决方案1】:

python 中的多线程问题之一是join() 或多或少会禁用信号。

这是因为信号只能传递给主线程,而主线程已经忙于执行join(),并且连接是不可中断的。

您可以从signal 模块的文档中推断出这一点

如果在同一个程序中同时使用信号和线程,则必须小心。同时使用信号和线程时要记住的基本事项是:始终在执行的主线程中执行 signal() 操作。任何线程都可以执行alarm()、getsignal()、pause()、setitimer()或getitimer();只有主线程可以设置新的信号处理程序,并且主线程将是唯一接收信号的线程(这是由 Python 信号模块强制执行的,即使底层线程实现支持向单个线程)。这意味着信号不能用作线程间通信的手段。请改用锁。

您可以通过忙循环连接操作来解决它:

for t in threads:
    while t.isAlive():
        t.join(timeout=1)

然而,这并没有效率:

使用超时调用 join() 的解决方法有一个缺点: Python 的线程等待例程每秒轮询 20 次 给定任何超时。所有这些轮询可能意味着大量 CPU 在其他空闲的笔记本电脑上中断/唤醒并耗尽 电池更快。

此处提供了更多详细信息:

Python program with thread can't catch CTRL+C

可以在此处找到有关此问题的错误报告以及对潜在问题的讨论:

https://bugs.python.org/issue1167930

https://bugs.python.org/issue1171023

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-09
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    相关资源
    最近更新 更多