1

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

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尝试的 - 这告诉主线程返回。

10 次中有 9 次,这将正常工作。程序将干净地退出。但是,有时我会收到以下两个错误:

错误一:

^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()生成器。就像我说的,这会从套接字产生网络数据。

你能看出我处理线程的方式有什么问题吗?

4

1 回答 1

2

KeyboardInterrupts任意线程接收。如果接收者不是主线程,它就会死掉,主线程不受影响,ThreadSpace.exit_flag保持为假,脚本继续运行。

如果你想sigint工作,你可以让每个线程捕获KeyboardInterrupt并调用thread.interrupt_main()以让 Python 退出,或者signal按照官方文档的说明使用模块。

于 2011-02-14T05:38:12.367 回答