簡體   English   中英

無法使用 Ctrl-C 終止 Python 腳本

[英]Cannot kill Python script with Ctrl-C

我正在使用以下腳本測試 Python 線程:

import threading

class FirstThread (threading.Thread):
    def run (self):
        while True:
            print 'first'

class SecondThread (threading.Thread):
    def run (self):
        while True:
            print 'second'

FirstThread().start()
SecondThread().start()

這是在 Kubuntu 11.10 上的 Python 2.7 中運行的。 Ctrl + C不會殺死它。 我還嘗試為系統信號添加處理程序,但這沒有幫助:

import signal 
import sys
def signal_handler(signal, frame):
    sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

為了殺死進程,我在使用Ctrl + Z將程序發送到后台后通過 PID 殺死它,這不會被忽略。 為什么Ctrl + C如此持久地被忽略? 我該如何解決這個問題?

Ctrl + C終止主線程,但是由於您的線程未處於守護程序模式,它們會繼續運行,從而使進程保持活動狀態。 我們可以讓它們成為守護進程:

f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()

但是還有另一個問題——一旦主線程啟動了你的線程,它就沒有什么可做的了。 所以它退出了,線程立即被銷毀。 所以讓我們保持主線程活着:

import time
while True:
    time.sleep(1)

現在它將保持打印“第一”和“第二”,直到您點擊Ctrl + C

編輯:正如評論者指出的那樣,守護線程可能沒有機會清理臨時文件之類的東西。 如果需要,則在主線程上捕獲KeyboardInterrupt並讓它協調清理和關閉。 但在很多情況下,讓守護線程突然死掉可能就足夠了。

KeyboardInterrupt 和信號只有進程(即主線程)才能看到...看看Ctrl-c 即 KeyboardInterrupt 以殺死 python 中的線程

我認為當您希望線程死亡時,最好在線程上調用join() 我冒昧地將您的循環更改為結束(您也可以在那里添加所需的任何清理需求)。 每次通過時都會檢查變量die ,當它為True時,程序退出。

import threading
import time

class MyThread (threading.Thread):
    die = False
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name

    def run (self):
        while not self.die:
            time.sleep(1)
            print (self.name)

    def join(self):
        self.die = True
        super().join()

if __name__ == '__main__':
    f = MyThread('first')
    f.start()
    s = MyThread('second')
    s.start()
    try:
        while True:
            time.sleep(2)
    except KeyboardInterrupt:
        f.join()
        s.join()

@Thomas K 答案的改進版本:

  • 根據這個要點定義一個輔助函數is_any_thread_alive() ,它可以自動終止main()

示例代碼:

import threading

def job1():
    ...

def job2():
    ...

def is_any_thread_alive(threads):
    return True in [t.is_alive() for t in threads]

if __name__ == "__main__":
    ...
    t1 = threading.Thread(target=job1,daemon=True)
    t2 = threading.Thread(target=job2,daemon=True)
    t1.start()
    t2.start()

    while is_any_thread_alive([t1,t2]):
        time.sleep(0)

要提防一個簡單的“陷阱”,您確定CAPS LOCK沒有打開嗎?

我在 Pi4 上的 Thonny IDE 中運行 Python 腳本。 啟用CAPS LOCK后, Ctrl + Shift + C被傳遞到鍵盤緩沖區,而不是Ctrl + C

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM