Я должен всегда указывать тип исключения, за исключением заявления?


при использовании PyCharm IDE использование except: без исключения тип вызывает напоминание из IDE, что это предложение исключения Too broad.

должен ли я игнорировать этот совет? Или это питон, чтобы всегда определять тип исключения?

7 55

7 ответов:

почти всегда лучше указать явный тип исключения. Если вы используете голый except: предложение, вы можете в конечном итоге поймать исключения, отличные от тех, которые вы ожидаете поймать - это может скрыть ошибки или затруднить отладку программ, когда они не делают то, что вы ожидаете.

например, если вы вставляете строку в базу данных, вы можете поймать исключение, которое указывает, что строка уже существует, поэтому вы можете выполнить обновление.

try:
    insert(connection, data)
except:
    update(connection, data)

если вы указываете голый except:, вы также поймаете ошибку сокета, указывающую, что сервер базы данных упал. Лучше всего ловить только исключения, которые вы знаете, как обрабатывать - часто лучше, чтобы программа потерпела неудачу в точке исключения, чем продолжать, но вести себя странно неожиданными способами.

один случай, когда вы можете использовать голый except: находится на верхнем уровне программы, которую вы должны всегда запускать, как сетевой сервер. Но тогда вы должны быть очень внимательно регистрируйте исключения, иначе будет невозможно понять, что происходит не так. В принципе, в программе должно быть не более одного места, которое делает это.

следствием всего этого является то, что ваш код никогда не должен делать raise Exception('some message') потому что это заставляет клиентский код использовать except: (или except Exception: что это почти как плохо). Вы должны определить исключение, специфичное для проблемы, которую вы хотите сигнализировать (возможно, наследуя от некоторого встроенного подкласса исключений, такого как ValueError или TypeError). Или вы должны создать определенное встроенное исключение. Это позволяет пользователям кода быть осторожными при отлове только тех исключений, которые они хотят обработать.

вы не должны игнорировать советы, которые дает вам переводчик.

С PEP-8 руководство по стилю для Python:

при перехвате исключений всегда указывайте конкретные исключения возможно вместо использования голыми, за исключением: пункта.

например, использовать:

 try:
     import platform_specific_module 
 except ImportError:
     platform_specific_module = None 

голый, за исключением: пункта поймать KeyboardInterrupt исключение SystemExit и, делая это тяжелее, чтобы прервать программа с управлением-C, и может замаскировать другие проблемы. Если вы хотите поймать все исключения, которые сигнализируют об ошибках программы, используйте за исключением исключений: (ничего, кроме эквивалентно, за исключением BaseException:).

хорошее правило большого пальца заключается в том, чтобы ограничить использование голого, за исключением статьи об двух случаи:

если обработчик исключений будет распечатка или запись вывод; по крайней мере, пользователь будет знать, что произошла ошибка. Если код должен сделать некоторую очистку работайте, но тогда давайте исключение распространяйте вверх с повышением. пытаться...наконец, может быть лучший способ разберись с этим делом.

не specfic для Python это.

весь смысл исключений заключается в том, чтобы решить проблему как можно ближе к тому, где она была вызвана.

таким образом, вы сохраняете код, который может в исключительных случаях вызвать проблему и разрешение "рядом" друг с другом.

дело в том, что вы не можете знать все исключения, которые могут быть брошены куском кода. Все, что вы можете знать, это то, что если это, скажем, файл не найден исключение, то вы можете поймать его и предложить пользователю получить тот, который делает или отменяет функцию.

Если вы поместите try catch вокруг этого, то независимо от того, какая проблема была в вашей рутине файла (только для чтения, разрешения, UAC, не совсем pdf и т. д.), Каждый из них зайдет в ваш файл не найден catch, и ваш пользователь кричит "но он есть, этот код-дерьмо"

сейчас есть пара ситуаций, когда вы могли бы поймать все, но они должны быть выбраны сознательно.

Они вы ловите, отменяете некоторые локальные действия (такие как создание или блокировка ресурса, (открытие файла на диске для записи, например), затем вы снова бросаете исключение, чтобы иметь дело с более высоким уровнем)

другой вы вы не заботитесь, почему это пошло не так. Например, печать. У вас может быть ловушка вокруг этого, чтобы сказать, что есть какая-то проблема с вашим принтером, пожалуйста, разберитесь, а не убейте приложение из-за этого. Ona подобное напрасно, если ваш код выполнил ряд отдельных задачи используя какой-то график, вы не хотели бы, чтобы все это умерло, потому что одна из задач не удалась.

Примечание Если вы делаете выше, я не могу рекомендовать какой-то журнал исключений, например, попробуйте поймать конец журнала, достаточно высоко.

вы также поймаете, например, Control-C с этим, поэтому не делайте этого, если вы не "бросите" его снова. Однако в этом случае вы должны скорее использовать "наконец".

всегда указывайте тип исключения, есть много типов, которые вы не хотите ловить, например SyntaxError,KeyboardInterrupt,MemoryError etc.

вот места, где я использую, кроме как без типа

  1. быстрое и грязное прототипирование

Это основное использование в моем коде для непроверенных исключений

  1. функция верхнего уровня main (), где я регистрирую каждое неперехваченное исключение

Я всегда добавляю это, чтобы производственный код не разливал stacktraces

  1. между слоями приложения

У меня есть два способа сделать это :

  • Первый способ сделать это: когда слой более высокого уровня вызывает функцию более низкого уровня, он переносит вызовы в типизированные исключения для обработки "верхних" исключений более низкого уровня. Но я добавляю общий оператор except, чтобы обнаружить необработанные исключения нижнего уровня в функциях нижнего уровня.

я предпочитаю это таким образом, мне легче определить, какие исключения должны были быть пойманы соответствующим образом : я" вижу " проблему лучше, когда исключение более низкого уровня регистрируется на более высоком уровне

  • Второй способ сделать это: у каждой функции верхнего уровня нижних уровней есть свой код, завернутый в общий except, чтобы он ловил все необработанные исключения на этом конкретном слое.

некоторые коллеги предпочитают этот способ, так как он сохраняет исключения более низкого уровня в функциях более низкого уровня, где они "принадлежат".

попробуйте это:

try:
    #code
except ValueError:
    pass

Я получил ответ по этой ссылке, если кто-то еще столкнется с этой проблемой зацените