我的 KeyboardInterrupt 仅在 90% 的情况下被捕获。我在什么方面失败了?
下面是一些精简的代码,演示了我对线程的使用:
import threading
import Queue
import time
def example():
""" used in MainThread as the example generator """
while True:
yield 'asd'
class ThreadSpace:
""" A namespace to be shared among threads/functions """
# set this to True to kill the threads
exit_flag = False
class MainThread(threading.Thread):
def __init__(self, output):
super(MainThread, self).__init__()
self.output = output
def run(self):
# this is a generator that contains a While True
for blah in example():
self.output.put(blah)
if ThreadSpace.exit_flag:
break
time.sleep(0.1)
class LoggerThread(threading.Thread):
def __init__(self, output):
super(LoggerThread, self).__init__()
self.output = output
def run(self):
while True:
data = self.output.get()
print data
def main():
# start the logging thread
logging_queue = Queue.Queue()
logging_thread = LoggerThread(logging_queue)
logging_thread.daemon = True
logging_thread.start()
# launch the main thread
main_thread = MainThread(logging_queue)
main_thread.start()
try:
while main_thread.isAlive():
time.sleep(0.5)
except KeyboardInterrupt:
ThreadSpace.exit_flag = True
if __name__ == '__main__':
main()
我有一个主线程,它获取从阻塞生成器生成的数据。在实际代码中,该生成器生成通过套接字嗅探出来的网络相关数据。
然后我有一个日志记录、守护进程、线程,它将数据打印到屏幕上。
为了干净地退出程序,我捕获了一个KeyboardInterrupt
,它将设置一个exit_flag
来尝试 - 这告诉主线程返回。
十有八九,这样就可以了。程序将干净退出。但是,在某些情况下,我会收到以下两个错误:
错误 1:
^CTraceback (most recent call last):
File "demo.py", line 92, in <module>
main('')
File "demo.py", line 87, in main
time.sleep(0.5)
KeyboardInterrupt
错误 2:
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored
我已经运行了这个确切的示例代码几次,但还没有'无法复制这些错误。此代码与真实代码之间的唯一区别是 example()
生成器。正如我所说,这会从套接字产生网络数据。
你能看出我处理线程的方式有什么问题吗?
Here's some slimmed down code that demonstrates my use of threading:
import threading
import Queue
import time
def example():
""" used in MainThread as the example generator """
while True:
yield 'asd'
class ThreadSpace:
""" A namespace to be shared among threads/functions """
# set this to True to kill the threads
exit_flag = False
class MainThread(threading.Thread):
def __init__(self, output):
super(MainThread, self).__init__()
self.output = output
def run(self):
# this is a generator that contains a While True
for blah in example():
self.output.put(blah)
if ThreadSpace.exit_flag:
break
time.sleep(0.1)
class LoggerThread(threading.Thread):
def __init__(self, output):
super(LoggerThread, self).__init__()
self.output = output
def run(self):
while True:
data = self.output.get()
print data
def main():
# start the logging thread
logging_queue = Queue.Queue()
logging_thread = LoggerThread(logging_queue)
logging_thread.daemon = True
logging_thread.start()
# launch the main thread
main_thread = MainThread(logging_queue)
main_thread.start()
try:
while main_thread.isAlive():
time.sleep(0.5)
except KeyboardInterrupt:
ThreadSpace.exit_flag = True
if __name__ == '__main__':
main()
I have one main thread which gets data yielded to it from a blocking generator. In the real code, this generator yields network related data it sniffs out over the socket.
I then have a logging, daemon, thread which prints the data to screen.
To exit the program cleanly, I'm catching a KeyboardInterrupt
which will set an exit_flag
to try - This tells the main thread to return.
9 times out of 10, this will work fine. The program will exit cleanly. However, there's a few occasions when I'll receive the following two errors:
Error 1:
^CTraceback (most recent call last):
File "demo.py", line 92, in <module>
main('')
File "demo.py", line 87, in main
time.sleep(0.5)
KeyboardInterrupt
Error 2:
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored
I've run this exact sample code a few times and haven't been able to replicate the errors. The only difference between this and the real code is the example()
generator. This, like I said, yields network data from the socket.
Can you see anything wrong with how I'm handling the threads?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
KeyboardInterrupts
由任意线程接收。如果接收者不是主线程,它就会终止,主线程不受影响,ThreadSpace.exit_flag 保持 false,并且脚本继续运行。如果您希望
sigint
工作,您可以让每个线程捕获KeyboardInterrupt
并调用thread.interrupt_main()
让Python退出,或者使用signal
模块,如官方文档所述。KeyboardInterrupts
are received by arbitrary threads. If the receiver isn't the main thread, it dies, the main thread is unaffected,ThreadSpace.exit_flag
remains false, and the script keeps running.If you want
sigint
to work, you can have each thread catchKeyboardInterrupt
and callthread.interrupt_main()
to get Python to exit, or use thesignal
module as the official documentation explains.