![](/img/trans.png)
[英]Python program works with raw_input() but not with 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.