Reputation: 13335
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?
Upvotes: 14
Views: 16629
Reputation: 55197
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.
Upvotes: 13
Reputation: 239443
You can try using BrokenPipeError
and if it throws a NameError
, then fall back to socket.error
, like this
import socket
try:
expected_error = BrokenPipeError
except NameError:
expected_error = socket.error
And then use it like this
try:
1 == 2
except expected_error as ex:
# Handle the actual exception here
Upvotes: 6