При использовании PyCharm IDE использование типа except:
без исключения вызывает напоминание от IDE о том, что это предложение исключения Too broad
.
Стоит ли игнорировать этот совет? Или Pythonic всегда определяет тип исключения?
При использовании PyCharm IDE использование типа except:
без исключения вызывает напоминание от IDE о том, что это предложение исключения Too broad
.
Стоит ли игнорировать этот совет? Или Pythonic всегда определяет тип исключения?
Ответы:
Почти всегда лучше указать явный тип исключения. Если вы используете голое except:
предложение, вы можете в конечном итоге перехватить исключения, отличные от тех, которые вы ожидаете отловить - это может скрыть ошибки или усложнить отладку программ, когда они не делают того, что вы ожидаете.
Например, если вы вставляете строку в базу данных, вы можете захотеть перехватить исключение, которое указывает, что строка уже существует, чтобы вы могли выполнить обновление.
try:
insert(connection, data)
except:
update(connection, data)
Если вы укажете пустой except:
, вы также поймаете ошибку сокета, указывающую на то, что сервер базы данных упал. Лучше всего улавливать только те исключения, которые вы умеете обрабатывать - часто для программы лучше выйти из строя в точке исключения, чем продолжить, но вести себя странным и неожиданным образом.
Один случай, когда вы, возможно, захотите использовать голый, except:
- это верхний уровень программы, которую вам нужно всегда запускать, например, сетевой сервер. Но тогда вам нужно быть очень осторожным, чтобы регистрировать исключения, иначе будет невозможно понять, что идет не так. По сути, в программе должно быть только одно место, которое это делает.
Следствием всего этого является то, что ваш код никогда не должен работать, raise Exception('some message')
потому что он заставляет использовать клиентский код except:
(или except Exception:
что почти так же плохо). Вы должны определить исключение, специфичное для проблемы, о которой хотите сообщить (возможно, унаследовав от некоторого встроенного подкласса исключений, например ValueError
или TypeError
). Или вы должны вызвать конкретное встроенное исключение. Это позволяет пользователям вашего кода быть осторожными при отлове только тех исключений, которые они хотят обработать.
except:
также улавливает (среди многих других вещей) NameError
и AttributeError
, поэтому, если вы неправильно написали что-то в try
блоке (например, ваша функция "вставить" на самом деле вызывается, insert_one
потому что кто-то не ценит согласованность так, как должен), она всегда молча пытается update()
.
main()
)?
except Exception:
поймают NameError
и AttributeError
тоже. Что делает bare except:
настолько плохим, так это то, что он улавливает вещи, которые не имеют никакого отношения к ловле, например SystemExit
(поднимается, когда вы звоните exit
или sys.exit
, и теперь вы предотвратили предполагаемый выход) и KeyboardInterrupt
(опять же, если пользователь ударил Ctrl-C
, вы, вероятно, не захотите продолжать бежать им назло). Только последнее имеет смысл ловить, и его следует ловить явно. По крайней мере, except Exception:
позволяет этим двум нормально размножаться.
Вы не должны игнорировать советы, которые дает вам переводчик.
Из Руководства по стилю PEP-8 для Python:
При перехвате исключений по возможности упоминайте конкретные исключения вместо использования простого предложения except :.
Например, используйте:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Пустое предложение except: перехватит исключения SystemExit и KeyboardInterrupt, что затруднит прерывание программы с помощью Control-C и может замаскировать другие проблемы. Если вы хотите перехватить все исключения, которые сигнализируют об ошибках программы, используйте except Exception: (bare except эквивалентно except BaseException :).
Хорошее практическое правило - ограничить использование пустых предложений "за исключением" двумя случаями:
Если обработчик исключений будет распечатывать или регистрировать трассировку; по крайней мере, пользователь будет знать, что произошла ошибка. Если код должен выполнить некоторую работу по очистке, но затем позволяет исключению распространяться вверх с помощью повышения. попробуйте ... наконец-то может быть лучшим способом справиться с этим делом.
Это не относится к Python.
Весь смысл исключений состоит в том, чтобы решать проблему как можно ближе к тому месту, где она была вызвана.
Таким образом, вы храните код, который в исключительных обстоятельствах может вызвать проблему и решение, «рядом» друг с другом.
Дело в том, что вы не можете знать все исключения, которые могут быть вызваны фрагментом кода. Все, что вы можете знать, это то, что если это исключение, скажем, файл не найден, вы можете перехватить его и предложить пользователю получить то, которое выполняет или отменить функцию.
Если вы поставите try catch вокруг этого, то независимо от того, какая проблема была в вашей файловой процедуре (только чтение, разрешения, UAC, на самом деле не pdf и т. Д.), Каждый из них попадет в ваш файл, не найденный улов, и ваш пользователь кричит "но он там, этот код дерьмо"
Теперь есть пара ситуаций, когда вы можете поймать все, но их следует выбирать осознанно.
Они отлавливают, отменяют некоторые локальные действия (например, создание или блокировку ресурса (например, открытие файла на диске для записи), затем вы снова генерируете исключение, чтобы обработать его на более высоком уровне)
Другой - вам все равно, почему все пошло не так. Например, печать. Вы можете сказать, что с вашим принтером возникла какая-то проблема, пожалуйста, разберитесь с ней и не закрывайте приложение из-за этого. Точно так же напрасно, если ваш код выполнял серию отдельных задач, используя какое-то расписание, вы не захотели бы, чтобы все это умерло, потому что одна из задач не удалась.
Примечание. Если вы сделаете это выше, я не могу рекомендовать какой-либо вид ведения журнала исключений, например, достаточно попытаться поймать конец журнала.
Вы также поймаете, например, Control-C с этим, так что не делайте этого, пока вы не "бросите" его снова. Однако в этом случае лучше использовать «наконец».
Всегда указывайте тип исключения, есть много типов, которые вы не хотите перехватывать, например SyntaxError
, KeyboardInterrupt
и MemoryError
т. Д.
except Exception:
избежать перечисленных выше типов, которые мы не хотим ловить?
except Exception
Это хорошо.
except Exception
ловит SyntaxError
и MemoryError
потому, что это их базовый класс. KeyboardInterrupt
, SystemExit
(поднятые sys.exit()
) не улавливаются (они являются непосредственными подклассами BaseException)
Вот места, где я использую, кроме без типа
Это основное использование в моем коде непроверенных исключений
Я всегда добавляю это, чтобы производственный код не проливал следы стека
У меня есть два способа сделать это:
Я предпочитаю этот способ, мне легче определить, какие исключения должны были быть перехвачены надлежащим образом: я «вижу» проблему лучше, когда исключение более низкого уровня регистрируется более высоким уровнем
Некоторые сотрудники предпочитают этот способ, поскольку он сохраняет исключения более низкого уровня в функциях более низкого уровня, которым они «принадлежат».
Попробуй это:
try:
#code
except ValueError:
pass
Я получил ответ по этой ссылке, если кто-то еще столкнется с этой проблемой, проверьте это