Python多进程atexit错误“Error in atexit._run_exitfuncs”

18 投票
2 回答
31295 浏览
提问于 2025-04-15 11:42

我正在尝试在Python中运行一个简单的多进程应用程序。主线程会创建1到N个进程,并等待它们全部完成处理。每个进程都在无限循环中运行,所以它们可能会一直运行下去,直到用户手动中断。因此,我在代码中加入了一些处理键盘中断的代码:

#!/usr/bin/env python
import sys
import time
from multiprocessing import Process

def main():
    # Set up inputs..

    # Spawn processes
    Proc( 1).start()
    Proc( 2).start()

class Proc ( Process ):
    def __init__ ( self, procNum):
        self.id = procNum
        Process.__init__(self)

    def run ( self ):
        doneWork = False

        while True:

            try:
                # Do work...
                time.sleep(1)
                sys.stdout.write('.')

                if doneWork:
                    print "PROC#" + str(self.id) + " Done."
                    break

            except KeyboardInterrupt:
                print "User aborted."
                sys.exit()

# Main Entry
if __name__=="__main__":
    main()

问题是,当我使用CTRL-C来退出时,虽然进程似乎立刻退出了,但我却收到了一个额外的错误信息:

......User aborted.
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "C:\Python26\lib\atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "C:\Python26\lib\multiprocessing\util.py", line 281, in _exit_function
    p.join()
  File "C:\Python26\lib\multiprocessing\process.py", line 119, in join
    res = self._popen.wait(timeout)
  File "C:\Python26\lib\multiprocessing\forking.py", line 259, in wait
    res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt
Error in sys.exitfunc:
Traceback (most recent call last):
  File "C:\Python26\lib\atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "C:\Python26\lib\multiprocessing\util.py", line 281, in _exit_function
    p.join()
  File "C:\Python26\lib\multiprocessing\process.py", line 119, in join
    res = self._popen.wait(timeout)
  File "C:\Python26\lib\multiprocessing\forking.py", line 259, in wait
    res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt

我在Windows上运行的是Python 2.6。如果有更好的方法来处理Python中的多进程,请告诉我。

2 个回答

3

这是一个很早的问题,但看起来被接受的答案并没有真正解决这个问题。

主要的问题是,你还需要在父进程中处理键盘中断。此外,在while循环中,你只需要退出循环,不需要调用sys.exit()

我尽量让这个例子和原问题中的例子相似。原例子中的doneWork代码没有实际作用,所以为了清晰起见,我把它去掉了。

import sys
import time
from multiprocessing import Process


def main():
    # Set up inputs..

    # Spawn processes
    try:
        processes = [Proc(1), Proc(2)]
        [p.start() for p in processes]
        [p.join() for p in processes]
    except KeyboardInterrupt:
        pass


class Proc(Process):
    def __init__(self, procNum):
        self.id = procNum
        Process.__init__(self)

    def run(self):
        while True:
            try:
                # Do work...
                time.sleep(1)
                sys.stdout.write('.')

            except KeyboardInterrupt:
                print("User aborted.")
                break


# Main Entry
if __name__ == "__main__":
    main()
1

与其直接强制程序退出(用 sys.exit()),不如给你的线程发送一个信号,告诉它们停止工作。可以看看 Python 中的 信号处理器和线程的相关内容。

你可以尝试把 while True: 循环改成 while keep_processing:,其中 keep_processing 是一个全局变量,当你按下键盘中断(KeyboardInterrupt)时,这个变量会被设置。不过,我觉得这样做并不是一个好习惯。

撰写回答