I try to write some code to catch a Broken Pipe Error. The code should run in Python 2.x and Python 3.x.
In Python 2.x a broken pipe is represented by a socket.error
socket.error: [Errno 32] Broken pipe
This was changed in Python 3.x - a broken pipe now is a BrokenPipeError
BrokenPipeError: [Errno 32] Broken pipe
Also the syntax of exception handling has changed a bit (see https://stackoverflow.com/a/34463112/263589) so what I need to do would be something like:
try:
do_something()
except BrokenPipeError as e: # implies Python 3.x
resolve_for_python2()
except socket.error as e:
if sys.version_info[0] == 2: # this is necessary, as in Python >=3.3
# socket.error is an alias of OSError
# https://docs.python.org/3/library/socket.html#socket.error
resolve_for_python3()
else:
raise
There's (at least) one remaining problem: In Python 2.x there is no BrokenPipeError
, so whenever there is an exception in do_something()
Python 2.x would throw another exception and complain that it doesn't know BrokenPipeError
. As socket.error
is deprecated in Python 3.x a similar problem could arise in Python 3.x in the near future.
What can I do to make this code run in Python 2.x and Python 3.x?
Properly catching IOError to avoid Broken pipe error As a Broken pipe error is an IOError error, we can place a try/catch block in order to catch it, as shown in the following snippet of code: Syntax: import sys, errno.
Avoid [Errno 32] Broken pipe by ignoring SIGPIPE Do not set SIGPIPE 's disposition to SIG_DFL in order to avoid BrokenPipeError . Doing that would cause your program to exit unexpectedly also whenever any socket connection is interrupted while your program is still writing to it.
A "Broken Pipe" error occurs when you try to write to a pipe that has been closed on the other end. Since the code you've shown doesn't involve any pipes directly, I suspect you're doing something outside of Python to redirect the standard output of the Python interpreter to somewhere else.
Python interpreter is not capable enough to ignore SIGPIPE by default, instead, it converts this signal into an exception and raises an error which is known as IOError(INPUT/OUTPUT error) also know as 'Error 32' or Broken Pipe Error.
If all you care about are broken pipe errors, then you might want to catch socket.error
and simply check whether it's indeed a broken pipe error.
You can do so using the exception's errno
attribute, which is present in both Python 2 and Python 3, which means, you don't need different Python 2 vs. 3 logic (I'd argue the intent is a little clearer this way):
import socket
import errno
try:
do_something()
except socket.error as e:
if e.errno != errno.EPIPE:
# Not a broken pipe
raise
do_something_about_the_broken_pipe()
If you do care about more than broken pipes, thefourtheye's answer is appropriate and idiomatic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With