为什么我的子类多处理进程挂起?

时间:2013-05-03 02:51:09

标签: python-2.7 error-handling parallel-processing multiprocessing

我编写了一个Python程序,它通过子类化的Process对象采用多处理。我目前正在尝试改进错误处理,但是由于我无法理解的原因,这让我感到沮丧。

在我列出一些示例代码时请耐心等待:

我的子流程工作者:

# worker.py

from multiprocessing import Process, Queue
import sys
import traceback
# other imports as necessary

class Worker(Process):
    def __init__(self, inputQueue, outputQueue):
        try:
            super(Worker, self).__init__()

            self.inputQueue = inputQueue
            self.outputQueue = outputQueue

            #etc

            1/0 # dumb error that causes the process to crash

            #etc

         except Exception as e:
             exc_type, exc_value, exc_traceback = sys.exc_info()
             e = traceback.format_exception(exc_type, exc_value, exc_traceback, limit = 2)

             # Forward the error message to the Engine class
             self.outputQueue.put({ 'type' : 'error', 'data' : e })

    def run(self):
        try:
            for i in iter(self.inputQueue.get, 'STOP'):
                # Do stuff
                self.outputQueue.put({ 'type' : 'result', 'data' : stuff })

        except Exception as e:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            e = traceback.format_exception(exc_type, exc_value, exc_traceback, limit = 2)

            # Forward the error message to the Engine class
            self.outputQueue.put({ 'type' : 'error', 'data' : e })

这是我的Engine类,它是Worker对象的父级:

# engine.py
# imports as necessary
class Engine:
    def __init__(self) # Other arguments as necessary
        # Initialise the class
        self.processors = []
    def run(self):
        try:
            # Fill the inputQueue with a number of jobs
            # and initialise the output queue

            # etc

            # Start the Worker processes
            for i in range(numberOfProcesses):
                p = worker.Worker(inputQueue, outputQueue)
                self.processors.append(p)
                p.start()
                inputQueue.put('STOP')

            # Process outputQueue
            numberOfJobs = 6 # (say)

            while numberOfJobs:
                result = outputQueue.get()

                if result['type'] == 'error':
                    print result
                    raise Exception

                elif result['type'] == 'result':
                    # Process result appropriately
                    numberOfJobs -= 1

            for p in self.processors:
                p.join()

        except Exception as e:
            raise

运行整个事情的配置文件:

# configuration.py
if __name__ == "__main__":
    # Initialise other parameters as necessary

    try:
        # Initialise an instance of engine.Engine
        eng = engine.Engine(arguments as necessary)

        eng.run()

    except Exception as e:
        print e
        print 'Finished UNSUCCESSFULLY.'

    else:
        print 'Finished SUCCESSFULLY.'

为简洁起见,我在示例代码中留下了一些导入和其他内容。 worker.py中的错误处理机制来自我之前的问题here

当我运行程序时,工作进程执行,当一个人遇到Worker.__init__(或Worker.run()中的1/0错误时,如果其中有一个错误),它会抓取回溯并且将它放入输出队列就好了。 Engine.run()按预期打印错误消息。问题是这一切都结束了。引擎引发 new ,泛型,错误,并且(我认为)将其传递给configuration.py中的代码,然后程序应该通过except语句退出文件(打印一条消息,上面写着'完成不成功')。

相反,实际发生的是Engine.run()打印从Worker类派生的错误消息,然后程序挂起并且CPU使用率降至0%。没有其他事情发生。我认识到这很可能是其他工人流程没有退出的问题(或者他们应该做的任何事情)。

令我神秘的是,如果我在Engine类中没有except Exception as e块,并且我在configuration.py文件中没有try-except-else块,{{1从Worker对象打印回溯,然后使用通用Engine.run()语句正确崩溃(不挂起)。

基本上我想做的是让raise Exception将泛型引发异常传递给配置文件,以便程序更优雅地退出。

有人帮助我!

0 个答案:

没有答案