在Python中的Broken Pipe错误
如今,Python被认为是一种成熟的编程语言,由于其简单性和易读性语法,已被数据科学家和人工智能(AI)工程师广泛使用。除此之外,编程语言的模糊错误通常使新的程序员们为了调试代码而苦不堪言。
在接下来的教程中,我们将讨论一个经常在与文件系统交互时出现的著名错误消息 [Errno 32] Broken pipe 。我们还将了解其原因,以及避免和修复该错误的方法。
Python中导致”[Errno 32] Broken pipe”错误的原因是什么?
“Broken pipe”通常被视为 IOError (代表输入/输出错误)错误,该错误发生在Linux系统层面。它通常发生在读写文件,或者换句话说,在进行文件输入/输出或网络输入/输出(通过套接字)时。
在GNU libc错误代码中,该错误对应的Linux系统错误是 EPIPE 。
宏:int EPIPE
“Broken pipe.” 没有任何进程从管道的另一端读取数据。库中引发带有错误代码的每个函数也会发出 SIGPIPE 信号;如果没有处理或阻塞该信号,它将终止程序。因此,除非已经处理或阻塞了 SIGPIPE ,否则程序实际上不会显示 EPIPE 。
从上述说明可以看出,系统发送 SIGPIPE 信号会引发 [Errno 32] Broken pipe 错误,这是Linux的一种进程间通信机制。
例如,Linux系统还使用另一个称为 SIGINT 的信号。在Linux中,命令 Ctrl+C 会发送一个 SIGINT 信号以结束进程,或者我们可以使用 kill 命令来实现相同的效果。
Python不会默认忽略 SIGPIPE 信号。然而,它将该信号转换为异常并引发错误 - IOError: [Errno 32] Broken pipe ,每次接收到SIGPIPE信号时都会如此。
当在Linux终端中使用管道传输结果时出现的Broken Pipe错误
每当我们尝试将Python脚本的输出通过管道传输给另一个程序时,如果遇到 [Errno 32] Broken pipe 错误,例如以下示例:
示例:
$ python file_name.py | head
说明:
上述管道的语法将创建一个向上发送数据的过程和一个向下读取数据的过程。当向下不必读取向上的数据时,它会向向上的进程发送一个SIGPIPE信号。
向下不必读取向上的数据是什么时候呢?我们用一个示例来理解。在示例中, head 命令只需读取足够的行来告诉向上的进程我们不再需要读取它,然后它会向向上的进程发送SIGPIPE信号。
每当向上的进程是一个Python程序时,会发生类似 IOError: [Errno 32] Broken pipe 的错误。
如何避免Broken pipe错误
如果我们不关心正确捕捉SIGPIPE并且必须快速运行,可以在Python程序的顶部插入以下代码片段。
语法:
from signal import signal, SIGPIPE, SIG_DFL
#Ignore SIG_PIPE and don't throw exceptions on it... (http://docs.python.org/library/signal.html)
signal(SIGPIPE,SIG_DFL)
解释:
在上面的代码片段中,我们将 SIGPIPE 信号重定向到默认的 SIG_DFL ,系统通常会忽略该信号。
然而,建议在Python手册的信号库中小心处理SIGPIPE。
正确捕获IOError以避免”Broken pipe”错误
由于”Broken pipe”错误是一个 IOError 错误,我们可以使用 try/catch 块来捕获它,如下面的代码片段所示:
语法:
import sys, errno
try:
### IO operation ###
except IOError as e:
if e.errno == errno.EPIPE:
### Handle the error ###
解释:
在上面的代码片段中,我们导入了sys和errno模块,并放置了try/catch块,以便捕获并处理引发的异常。
多进程程序中”Broken pipe”错误的可能解决方案
在利用工作进程加快处理速度并利用多核CPU的程序中,我们可以尝试减少工作进程的数量,以检查错误是否仍然存在。
大量的工作进程可能会在尝试控制系统资源或权限以写入磁盘时发生冲突。