【问题标题】:What is the proper way to handle (in python) IOError: [Errno 4] Interrupted system call, raised by multiprocessing.Queue.get处理(在 python 中)IOError 的正确方法是什么:[Errno 4] Interrupted system call,由 multiprocessing.Queue.get 引发
【发布时间】:2012-12-17 15:43:22
【问题描述】:

当我使用 multiprocessing.Queue.get 时,有时由于 EINTR 会出现异常。

我肯定知道有时这种情况会无缘无故地发生(我在 tmux 缓冲区中打开另一个窗格),在这种情况下,我想继续工作并重试该操作。

我可以想象,在某些其他情况下,错误是有充分理由的,我应该停止运行或修复一些错误。

如何区分两者?

提前致谢

【问题讨论】:

  • 你应该确保队列在get之前不为空:if not queue.empty(): queue.get()
  • 我相信如果队列是空的,它只会阻塞调用。不会吗?在任何我不认为这是错误的原因。

标签: python error-handling queue multiprocessing ioerror


【解决方案1】:

老问题,现代解决方案:从 Python 3.5 开始,奇妙的PEP 475 - Retry system calls failing with EINTR 已经实现并为您解决问题。这是摘要:

标准库中提供的系统调用包装器应在它们因EINTR 而失败时自动重试,以减轻应用程序代码这样做的负担。

系统调用是指标准 C 库公开的与 I/O 或其他系统资源处理有关的函数。

基本上,系统会为您捕获并重试一段以EINTR 失败的代码,因此您不必再处理它。如果您的目标是较旧的版本,while True 循环仍然是要走的路。但是请注意,如果您使用的是 Python 3.3 或 3.4,则可以捕获专用异常 InterruptedError 而不是捕获 IOError 并检查 EINTR

【讨论】:

    【解决方案2】:

    当应用程序在等待其他输入时接收到信号时,许多系统调用会返回EINTR 错误。通常,这些信号可能是非常良性的,并且已经由 Python 处理,但底层系统调用最终仍会被中断。在进行 C/C++ 编码时,这是您不能完全依赖 sleep() 之类的函数的原因之一。 Python 库有时会在内部处理此错误代码,但显然在这种情况下它们不是。

    您可能有兴趣阅读讨论此问题的 this thread

    EINTR 的一般方法是简单地处理错误并再次重试操作 - 这对于队列上的 get() 方法应该是安全的。可以使用类似这样的方法,将队列作为参数传递并替换队列上 get() 方法的使用:

    import errno
    
    def my_queue_get(queue, block=True, timeout=None):
        while True:
            try:
                return queue.get(block, timeout)
            except IOError, e:
                if e.errno != errno.EINTR:
                    raise
    
    # Now replace instances of queue.get() with my_queue_get(queue), with other
    # parameters passed as usual.
    

    通常你不需要担心 Python 程序中的EINTR,除非你知道你正在等待一个特定的信号(例如SIGHUP)并且你已经安装了一个信号处理程序来设置一个标志和依靠代码的主体来拿起标志。在这种情况下,如果收到EINTR,您可能需要跳出循环并检查信号标志。

    但是,如果您没有使用任何信号处理,那么您应该能够忽略 EINTR 并重复您的操作 - 如果 Python 本身需要对信号进行处理,它应该已经在信号中处理了它处理程序。

    【讨论】:

    • 我无法投票,因为我的名声太小...谢谢您的回答!
    • 在没有太多知识的情况下,该做什么并不是那么明显,但我用 my_queue_get(result) 替换了 result.get()。我相信这是应该做的,以防其他人想知道如何使用代码..
    • 是的,它有点模糊 - 我已经更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多