IOError:[Errno 32]管道断开:Python

2024-04-19 16:03:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个非常简单的Python 3脚本:

f1 = open('a.txt', 'r')
print(f1.readlines())
f2 = open('b.txt', 'r')
print(f2.readlines())
f3 = open('c.txt', 'r')
print(f3.readlines())
f4 = open('d.txt', 'r')
print(f4.readlines())
f1.close()
f2.close()
f3.close()
f4.close()

但它总是说:

IOError: [Errno 32] Broken pipe

我在网上看到了所有复杂的修复方法,但是我直接复制了这段代码,所以我认为代码有问题,而不是Python的SIGPIPE。

我正在重定向输出,因此如果上面的脚本名为“open.py”,那么我要运行的命令是:

open.py | othercommand

Tags: 代码pytxt脚本closeopenf2f1
3条回答

要将Alex L.'s helpful answerakhan's helpful answerBlckknght's helpful answer与一些附加信息结合起来:

  • Standard Unix signal ^{}被发送到进程在没有进程从管道读取时将写入到pipe

    • 这不一定是一个错误条件;一些Unix实用程序,如head在设计上在接收到足够的数据后,会过早地停止从管道中读取数据。
  • 默认情况下-即,如果写入过程没有显式地陷阱SIGPIPE-则写入过程简单地终止,其退出代码设置为141,其计算公式为128(一般为信号终止)+13SIGPIPE的特定信号个数)。

  • 然而,通过设计,Python本身陷阱SIGPIPE将其转换为具有errnoerrno.EPIPE的Python IOError实例,以便Python脚本可以捕获它,如果它选择这样做的话-请参阅Alex L.'s answer了解如何执行该操作。

  • 如果Python脚本没有捕获它,Python将输出错误消息IOError: [Errno 32] Broken pipe,并使用退出代码1终止脚本-这就是OP saw的症状。

  • 在许多情况下,这比有用的更具破坏性,因此希望恢复到默认行为:

    • 使用signal模块只允许如下所述,如akhan's answer^{}将信号作为第一个参数处理,将处理程序作为第二个参数;特殊处理程序值SIG_DFL表示系统的默认行为:

      from signal import signal, SIGPIPE, SIG_DFL
      signal(SIGPIPE, SIG_DFL) 
      

我没有重现这个问题,但也许这个方法可以解决这个问题:(逐行写入stdout,而不是使用print

import sys
with open('a.txt', 'r') as f1:
    for line in f1:
        sys.stdout.write(line)

你能抓住断了的管子吗?这会将文件逐行写入stdout,直到管道关闭。

import sys, errno
try:
    with open('a.txt', 'r') as f1:
        for line in f1:
            sys.stdout.write(line)
except IOError as e:
    if e.errno == errno.EPIPE:
        # Handle error

您还需要确保在管道变大之前othercommand正在从管道中读取数据-https://unix.stackexchange.com/questions/11946/how-big-is-the-pipe-buffer

这个问题是由于SIGPIPE处理造成的。可以使用以下代码解决此问题:

from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE,SIG_DFL) 

See here了解此解决方案的背景信息。最好回答here

相关问题 更多 >