简体   繁体   English

Ctrl+c 不停止 Windows + python3.7 中的线程

[英]Ctrl+c not stopping a Thread in Windows + python3.7

I'm trying this simple thread with a while loop inside.我正在尝试这个简单的线程,里面有一个 while 循环。 When I'm inside the while loop, Ctrl+C has no effect in stopping my program.当我在 while 循环中时, Ctrl+C 对停止我的程序无效。 Once I go do something else after the while loop, the script stops as intended.一旦我在 while 循环之后做其他事情,脚本就会按预期停止。 What can I do so my script can be gracefully killed both while being in the while loop and after?我该怎么做才能在 while 循环中和之后优雅地终止我的脚本? ( Edit: This seems to be a problem exclusive to Windows, iOS and Ubuntu seem to do what I want) 编辑:这似乎是 Windows 独有的问题,iOS 和 Ubuntu 似乎可以做我想做的事)

import time, threading


class MainClass(threading.Thread):

    def __init__(self):
        super().__init__()

    def run(self):
        while True:
            time.sleep(1)
            print("Looping")


# Script entry point
if __name__ == '__main__':

    a = MainClass()
    a.daemon = True
    a.start()
    a.join()

This is a known issue, explained in Issue 35935 .这是一个已知问题,在问题 35935 中进行了解释。

A way to solve it is to use an event, which is passed into the thread class, which waits for the SIGINT to be triggered.一种解决方法是使用一个事件,该事件被传递到线程类中,等待 SIGINT 被触发。 As I understand, a way to overcome the fact that the main thread is blocking the event signal is to revert to the default kernel behaviour of SIGINT using signal.signal(signal.SIGINT, signal.SIG_DFL) , (solution pointed out by the issue OP), and the meaning of SIG_DFL is explained fe here .据我了解,克服主线程阻塞事件信号这一事实的方法是使用signal.signal(signal.SIGINT, signal.SIG_DFL)恢复到 SIGINT 的默认内核行为,(问题指出的解决方案OP), SIG_DFL 的含义解释为 fe here As to why this has to be the case is beyond the scope of my knowledge.至于为什么必须如此,超出了我的知识范围。

This is by no means a perfect solution, but works on Windows using Python 3.8+.这绝不是一个完美的解决方案,但可以在使用 Python 3.8+ 的 Windows 上运行。

Implementation:执行:

import time, threading
import signal


class MainClass(threading.Thread):

    def __init__(self,event):
        super().__init__()
        self.event = event

    def run(self):
        while not event.is_set():
            time.sleep(1)
            print("Looping")


# Script entry point
if __name__ == '__main__':
    try:
        event = threading.Event()
        a = MainClass(event)
        a.daemon=True
        a.start()
       
        signal.signal(signal.SIGINT, signal.SIG_DFL)

        event.wait()
    except KeyboardInterrupt:
        event.set()
        sys.exit(1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM