我的 KeyboardInterrupt 仅在 90% 的情况下被捕获。我在什么方面失败了?

发布于 2024-10-17 09:28:26 字数 2201 浏览 3 评论 0原文

下面是一些精简的代码,演示了我对线程的使用:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无声情话 2024-10-24 09:28:26

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 catch KeyboardInterrupt and call thread.interrupt_main() to get Python to exit, or use the signal module as the official documentation explains.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文