簡體   English   中英

python threading:如何中斷主線程並使其執行其他操作

[英]python threading: how to interrupt the main thread and make it do something else

使用python線程,是否可以中斷主線程而不終止它並要求它做其他事情?

例如,

def watch():
    while True:
        sleep(10)
        somethingWrong = check()
        if somethingWrong:
            raise Exception("something wrong")
try:
    watcher = threading.Thread(target=watch)
    watcher.start()
    doSomething() # This function could run several days and it cannot detect something wrong within itself, so I need the other thread watcher to check if this function perform well. In case of malfunction, the watcher should interrupt this function and ask the main thread to doSomethingElse
except:
    doSomethingElse()

在這個程序中,當線程watcher器中引發異常並保持doSomething時,主線程不受影響。 我希望子線程中引發的異常傳播到主線程並使主線程doSomethingElse 。我該怎么做?

請注意,在這個平台上提出的許多與此類似的問題實際上是無關緊要的。 在這些情況下,主線程正在等待來自子線程的消息。 但就我而言,主線程正在做某事。 那些 anwsers 在這里不適用的原因是主線程不能做某事並同時監聽子線程。

您可以向進程發送SIGINT信號。 SIGINT信號將轉換為KeyboardInterrupt異常,因此您可以在except KeyboardInterrupt:塊中處理此信號

筆記:

Python 信號處理程序總是在主解釋器的主 Python 線程中執行,即使信號是在另一個線程中接收到的。 這意味着信號不能用作線程間通信的手段。 您可以改用 threading 模塊中的同步原語。

import signal,os

def watch():
    while True:
        sleep(10)
        somethingWrong = check()
        if somethingWrong:
            os.kill(os.getpid(),signal.SIGINT)
try:
    watcher = threading.Thread(target=watch)
    watcher.start()
    doSomething()
except KeyboardInterrupt:
    doSomethingElse()

我認為下面的代碼將解決您的問題。

我們需要知道:

Python 信號處理程序總是在主解釋器的主 Python 線程中執行,即使信號是在另一個線程中接收到的

我們在子線程中發送我們的進程SIGUSR1信號。

SIGUSR1 和 SIGUSR2信號被放在一邊,供您以任何方式使用。 如果您在接收信號的程序中為它們編寫信號處理程序,它們對於簡單的進程間通信很有用。

在我們的例子中,這些信號將在主線程中處理。 當子線程向自己的進程發送信號時,信號處理程序在主線程中運行,我們將在信號處理程序中拋出異常。 在該異常之后,您的do_Something()捕獲此異常並將進入SubThreadException塊,在此塊中您可以進行一些清理。 cleanup()之后,我們再次拋出SubThreadException ,因為我們需要運行您的doSomethingElse()函數。

class SubThreadException(Exception):
    pass

def usr1_handler(signum, frame):
    raise SubThreadException()

signal.signal(signal.SIGUSR1,usr1_handler) 

def watch():
    while True:
        sleep(10)
        somethingWrong = check()
        if somethingWrong:
            os.kill(os.getpid(),signal.SIGUSR1)
                    
def doSomething():
    try:
        #your work here
    except SubThreadException:
        cleanup() #your cleanup, like close the file,flush the buffer
        raise SubThreadException
        
try:
    watcher = threading.Thread(target=watch)
    watcher.start()
    doSomething() # This function could run several days and it cannot detect something wrong within itself, so I need the other thread watcher to check if this function perform well. In case of malfunction, the watcher should interrupt this function and ask the main thread to doSomethingElse
except SubThreadException:
    doSomethingElse()

但是在 python 信號模塊文檔中提到了一些情況:

如果信號處理程序引發異常,異常將傳播到主線程,並且可能在任何字節碼指令之后引發。 最值得注意的是,KeyboardInterrupt 可能會在執行期間的任何時候出現。 大多數 Python 代碼,包括標准庫,都無法針對這種情況變得健壯,因此 KeyboardInterrupt(或由信號處理程序產生的任何其他異常)可能會在極少數情況下使程序處於意外狀態

暫無
暫無

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

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