Python SIGINT没有被捕获

myo*_*oan 3 python multithreading sigint

我无法理解为什么我的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()
Run Code Online (Sandbox Code Playgroud)

要清理这段代码,我更喜欢尝试/除了join()并在异常情况下关闭所有线程,这会有用吗?

dhk*_*hke 7

python中多线程的一个问题是join()或多或少地禁用了信号.

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

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

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

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

for t in threads:
    while t.isAlive():
        t.join(timeout=1)
Run Code Online (Sandbox Code Playgroud)

但是,这没有效率:

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

这里提供了更多细节:

带线程的Python程序无法捕获CTRL + C.

可以在此处找到有关此问题的Bug报告以及对基础问题的讨论:

https://bugs.python.org/issue1167930

https://bugs.python.org/issue1171023