IOError: [Errno 32] Broken pipe 错误分析

一、概述

Broken pipe 本质是 IOError 错误,是 Linux 系统层面的机制导致,一般发生在读写文件IO和网络Socket IO的时候。

对应的 Linux 系统错误是 EPIPE,摘自【参考2】的一段话:

'''
Macro: int EPIPE “Broken pipe.” 
There is no process reading from the other end of a pipe. 
Every library function that returns this error code also generates a SIGPIPE signal; 
this signal terminates the program if not handled or blocked. 
Thus, your program will never actually see EPIPE unless it has handled or blocked SIGPIPE.
'''

从这段话,我们可以知道这个错误是由系统 SIGPIPE 信号引起的,信号是 Linux 的一种进程间通信的机制,例如 ctrl+c 就会发送 SIGINT 信号来结束进程,或者使用 kill 命令。

$ kill 

那么 SIGPIPE 信号是由什么来引发的呢?Linux 系统中还有个常见的 Pipe 管道机制,多个命令的组合就会使用到管道。

python .py | head

管道存在上游发送数据的进程,下游读取数据的进程,在下游不再需要读取上游数据的时候,就会发送 SIGPIPE 信号给上游进程。

什么时候会出现下游不再需要读取上游数据了呢?例如示例中的 head 命令,只需要读够足够的行数,就可以告诉上游我已经不需要再读取了,就会发送 SIGPIPE 信号给上游进程。

当这个上游进程是 Python 程序的时候,就会出现 IOError: [Errno 32] Broken pipe 这样的错误。

原因是:python将这种管道截取的操作当成是一种输出异常,导致异常退出。

解决方式,用try ... except Exception捕获异常即可。

二、解决方法

# 方法1:捕获异常

import sys, errno
try:
    ### IO operation ###
except IOError as e:
    if e.errno == errno.EPIPE:
        ### Handle error ###

# 方法2:忽略信号
from signal import signal, SIGPIPE, SIG_DFL, SIG_IGN
signal(SIGPIPE, SIG_IGN)

# 恢复默认信号行为的方法
# signal(SIGPIPE, SIG_DFL)

 

你可能感兴趣的:(python基础)