Python 多处理 atexit 错误“Error in atexit._run_exitfuncs”

发布于 2024-07-20 13:07:00 字数 2076 浏览 6 评论 0原文

我正在尝试用 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 中处理多处理,请告诉我。

I am trying to run a simple multiple processes application in Python. The main thread spawns 1 to N processes and waits until they all done processing. The processes each run an infinite loop, so they can potentially run forever without some user interruption, so I put in some code to handle a KeyboardInterrupt:

#!/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()

The problem is that when using CTRL-C to exit, I get an additional error even though the processes seem to exit immediately:

......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

I am running Python 2.6 on Windows. If there is a better way to handle multiprocessing in Python, please let me know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

2024-07-27 13:07:00

这是一个非常古老的问题,但似乎接受的答案并没有真正解决问题。

主要问题是您还需要在父进程中处理键盘中断。 除此之外,在 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()

This is a very old question, but it seems like the accepted answer does not actually fix the problem.

The main issue is that you need to handle the keyboard interrupt in the parent process as well. Additionally to that, in the while loop, you just need to exit the loop, there's no need to call sys.exit()

I've tried to as closely match the example in the original question. The doneWork code does nothing in the example so have removed that for clarity.

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()
迷你仙 2024-07-27 13:07:00

您想要向线程发送信号以告诉它们停止,而不是仅仅强制 sys.exit()。 研究在 Python 中使用 信号处理程序 和线程。

您可以通过将 while True: 循环更改为 while keep_processing: 来实现此目的,其中 keep_processing 是设置为的某种全局变量键盘中断异常。 但我认为这不是一个好的做法。

Rather then just forcing sys.exit(), you want to send a signal to your threads to tell them to stop. Look into using signal handlers and threads in Python.

You could potentially do this by changing your while True: loop to be while keep_processing: where keep_processing is some sort of global variable that gets set on the KeyboardInterrupt exception. I don't think this is a good practice though.

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