我有一个等待输入的线程,但是如果没有提供输入,我需要退出该程序。我该如何退出该计划?在这个例子中,退出应该由键盘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)
答案 0 :(得分:1)
您可以使用signal.alarm()
在一段时间后向您的计划发送SIGALRM
(在此处定义为秒):
if __name__ == '__main__':
# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, shutdownHook)
signal.alarm(5)
以下是文档中的complete working example:
这是一个最小的示例程序。它使用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
至于为什么你的程序没有退出是因为quoted the doc
Python信号处理程序总是在主Python线程中执行, 即使信号是在另一个线程中收到的。这意味着 信号不能用作线程间通信的手段。您 可以使用来自线程模块的同步原语 代替。此外,只允许主线程设置新的信号处理程序。
这意味着您的线程无法像设计程序那样接收信号。实际上,如果您尝试在线程中设置信号,您将收到ValueError
:
ValueError: signal only works in main thread
这就是为什么您的程序在收到SIGTERM
后继续转动的原因。因为线程没有收到信号。
请参阅此处:Kill python thread using os替代解决方案。
答案 1 :(得分:-1)
将线程设为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)