簡體   English   中英

退出程序卡在sys.stdin.readline上

[英]exit program stuck on sys.stdin.readline

我有一個線程在等待輸入,但是在沒有提供輸入的情況下,我需要退出程序。 我如何退出該程序? 在此示例中,退出應該由鍵盤ctrl + c觸發,但是我也想在不進行交互(例如通過超時或其他事件)的情況下執行此操作。

import threading
import signal
import sys
import time

shutdown = False

def shutdownHook(sigNum, currentStackFrame):
        global shutdown
        print('shutdown')
        shutdown = True

def readInput():
        print('readInput')
        print(sys.stdin.readline())
        print('done reading input')

if __name__ == '__main__':
        signal.signal(signal.SIGINT, shutdownHook)
        signal.signal(signal.SIGTERM, shutdownHook)

        inputThread = threading.Thread(name='input', target=readInput)
        inputThread.start()
        print('started input')

        while not shutdown:
                time.sleep(1)
                print('waiting ' + str(shutdown))
        print('current thread' + str(threading.current_thread()))
        print('end of program ' + str(shutdown))
        sys.exit(0)

您可以使用signal.alarm()在特定時間(在此定義為秒)之后將SIGALRM發送到您的程序:

if __name__ == '__main__':
    # Set the signal handler and a 5-second alarm
    signal.signal(signal.SIGALRM, shutdownHook)
    signal.alarm(5)

這是文檔中完整的工作示例

這是一個最小的示例程序。 它使用alarm()函數來限制打開文件所花費的時間; 如果該文件用於可能無法打開的串行設備,這通常會導致os.open()無限期掛起,則這很有用。 解決的辦法是在打開文件之前設置5秒警報。 如果操作花費的時間太長,則會發送警報信號,並且處理程序將引發異常。

import signal, os

def handler(signum, frame):
    print('Signal handler called with signal', signum)
    raise OSError("Couldn't open device!")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Disable the alarm

至於為什么您的程序不退出是因為引用了文檔

即使在另一個線程中接收到信號,Python信號處理程序也總是在主Python線程中執行。 這意味着信號不能用作線程間通信的手段。 您可以改用來自線程模塊的同步原語。 此外,僅允許主線程設置新的信號處理程序。

這意味着您的線程在設計程序時不會收到任何信號。 實際上,如果您嘗試在線程中設置信號,則會收到ValueError

ValueError: signal only works in main thread

這就是為什么您的程序在收到SIGTERM之后仍保持轉動的原因。 因為線程沒有收到信號。

請參閱此處: 使用os殺死python線程以獲取替代解決方案。

將線程設置為Deamon線程,這樣在退出主線程時也將關閉。

inputThread = threading.Thread(name='input', target=readInput)
inputThread.setDaemon(True) # add this line
inputThread.start()

另外,您可以添加指定時間段內沒有活動的時間間隔。

time_limit_for_shutdown_in_secs = 10 
secs = 0
while not shutdown:
        if secs > time_limit_for_shutdown_in_secs: break
        time.sleep(1)
        print('waiting ' + str(shutdown))
        secs += 1

print('current thread' + str(threading.current_thread()))
print('end of program ' + str(shutdown))
sys.exit(0)

暫無
暫無

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

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