Поймать сломанную трубу в Python 2 и Python 3
Я пытаюсь написать некоторый код, чтобы поймать ошибку Broken Pipe. Код должен работать в Python 2.x и Python 3.x.
В Python 2.x разорванный канал представлен socket.error
socket.error: [Errno 32] Broken pipe
Это было изменено в Python 3.x - сломанная труба теперь BrokenPipeError
BrokenPipeError: [Errno 32] Broken pipe
Также немного изменился синтаксис обработки исключений (см. /questions/24940317/dejstvitelnyij-sintaksis-v-python-2x-i-3x-dlya-vozbuzhdeniya-isklyucheniya/24940325#24940325), так что мне нужно сделать что-то вроде:
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
Есть (по крайней мере) одна остающаяся проблема: в Python 2.x нет BrokenPipeError
поэтому, когда есть исключение в do_something()
Python 2.x выдает еще одно исключение и жалуется, что не знает BrokenPipeError
, Как socket.error
не рекомендуется в Python 3.x аналогичная проблема может возникнуть в Python 3.x в ближайшем будущем.
Что я могу сделать, чтобы этот код работал в Python 2.x и Python 3.x?
2 ответа
Если все, что вас волнует, это ошибки сломанной трубы, то вы можете захотеть отловить socket.error
и просто проверьте, действительно ли это ошибка сломанной трубы.
Вы можете сделать это с помощью исключения errno
атрибут, который присутствует как в Python 2, так и в Python 3, что означает, что вам не нужна разная логика Python 2 против 3 (я бы сказал, что намерение немного яснее в этом смысле):
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()
Если вы заботитесь не только о сломанных трубах, ответ thetheyeye уместен и идиоматичен.
Вы можете попробовать использовать BrokenPipeError
и если он бросает NameError
затем отступите к socket.error
, как это
import socket
try:
expected_error = BrokenPipeError
except NameError:
expected_error = socket.error
А потом использовать это так
try:
1 == 2
except expected_error as ex:
# Handle the actual exception here