Почему «кроме: пройти» плохая практика программирования?


325

Я часто вижу комментарии к другим вопросам переполнения стека о том, как except: passне рекомендуется использовать. Почему это плохо? Иногда мне просто все равно, что это за ошибки, и я просто хочу продолжить с кодом.

try:
    something
except:
    pass

Почему использование except: passблока плохо? Что делает это плохо? Это тот факт, что я passошибаюсь или я exceptошибаюсь?


1
Это самое меньшее, я бы посоветовал вам войти в систему, чтобы вы ЗНАЛИ, какие проблемы вы игнорируете. Используйте loggingмодуль на уровне DEBUG, чтобы избежать их использования в производственной среде, но оставляйте их в разработке.
августа

Ответы:


346

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

Мое объяснение «немного» длиннее - так что д-р разбивается на следующее:

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

Но давайте углубимся в детали:

Не лови ни одной ошибки

При использовании tryблока вы обычно делаете это, потому что знаете, что есть вероятность возникновения исключения. Таким образом, у вас также уже есть приблизительное представление о том, что может сломаться и какое исключение может быть выдано. В таких случаях вы ловите исключение, потому что вы можете восстановить после него. Это означает, что вы подготовлены к исключению и имеете какой-то альтернативный план, которому вы будете следовать в случае этого исключения.

Например, когда вы просите пользователя ввести число, вы можете преобразовать ввод, используя int()который может вызвать a ValueError. Вы можете легко восстановить это, просто попросив пользователя повторить попытку, поэтому перехват ValueErrorи повторный запрос пользователя будут подходящим планом. Другой пример - если вы хотите прочитать какую-то конфигурацию из файла, а этот файл не существует. Поскольку это файл конфигурации, у вас может быть некоторая конфигурация по умолчанию в качестве запасного варианта, поэтому файл не является абсолютно необходимым. Так что поймать FileNotFoundErrorи просто применить конфигурацию по умолчанию было бы хорошим планом здесь. Теперь в обоих этих случаях у нас есть очень конкретное исключение, которое мы ожидаем, и у нас есть одинаково конкретный план восстановления после него. Таким образом , в каждом конкретном случае, мы явно только except что определенные исключение.

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

Давайте рассмотрим пример файла конфигурации сверху. В случае отсутствия файла мы просто применили нашу конфигурацию по умолчанию и на более позднем этапе могли бы решить автоматически сохранить конфигурацию (поэтому в следующий раз файл будет существовать). Теперь представьте, что мы получаем IsADirectoryErrorилиPermissionErrorвместо. В таких случаях мы, вероятно, не хотим продолжать; мы все еще можем применить нашу конфигурацию по умолчанию, но позже мы не сможем сохранить файл. И вполне вероятно, что пользователь хотел иметь собственную конфигурацию, поэтому использование значений по умолчанию, скорее всего, нежелательно. Поэтому мы бы хотели немедленно сообщить об этом пользователю и, возможно, прервать выполнение программы. Но это не то, что мы хотим сделать где-то глубоко внутри какой-то небольшой части кода; это что-то важное на уровне приложения, поэтому его нужно обрабатывать наверху, поэтому пусть возникнет исключение.

Другой простой пример также упоминается в документе идиом Python 2 . Здесь в коде существует простая опечатка, которая приводит к ее поломке. Поскольку мы ловим каждое исключение, мы также ловим NameErrors и SyntaxErrors . Обе ошибки случаются со всеми нами во время программирования; и обе эти ошибки мы абсолютно не хотим включать при отправке кода. Но поскольку мы также поймали их, мы даже не узнаем, что они там произошли, и потеряем какую-либо помощь для их правильной отладки.

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

В любом случае, очень маловероятно, что вы подготовлены ко всему в небольшой части кода, поэтому на самом деле вы должны ловить только те исключения, к которым вы подготовлены. Некоторые люди предлагают по крайней мере поймать, Exceptionпоскольку это не будет включать в себя такие вещи, как SystemExitи KeyboardInterruptкоторые по замыслу должны прекратить ваше приложение, но я бы сказал, что это все еще слишком неопределенно. Есть только одно место, где я лично принимаю ловлю Exceptionили просто любоеисключение, и это в едином глобальном обработчике исключений уровня приложения, который имеет единственную цель - записать любое исключение, к которому мы не были подготовлены. Таким образом, мы все еще можем хранить как можно больше информации о непредвиденных исключениях, которые мы затем можем использовать для расширения нашего кода, чтобы обрабатывать их явно (если мы сможем восстановить их) или - в случае ошибки - для создания тестовых случаев, чтобы убедиться, это больше не повторится. Но, конечно, это работает, только если мы поймаем те исключения, которые мы уже ожидали, поэтому те, которые мы не ожидали, естественно всплывают.

Старайтесь избегать прохода, кроме блоков

Если явно отлавливать небольшую подборку конкретных исключений, существует множество ситуаций, в которых мы будем в порядке, просто ничего не делая. В таких случаях просто иметь except SomeSpecificException: passхорошо. Однако в большинстве случаев это не так, поскольку нам, вероятно, понадобится некоторый код, связанный с процессом восстановления (как упомянуто выше). Это может быть, например, то, что повторяет действие снова, или вместо этого установить значение по умолчанию.

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

def askForNumber ():
    while True:
        try:
            return int(input('Please enter a number: '))
        except ValueError:
            pass

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

Тем не менее, во многих других случаях простое указание exceptявляется признаком того, что мы не были готовы к исключению, которое мы ловим. Если эти исключения не являются простыми (например, ValueErrorили TypeError), и причина, по которой мы можем пройти, очевидна, старайтесь избегать просто передачи. Если на самом деле нечего делать (и вы абсолютно уверены в этом), подумайте над добавлением комментария, почему это так; в противном случае разверните блок исключения, чтобы фактически включить некоторый код восстановления.

except: pass

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


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


1
«Вы, по крайней мере, хотите зарегистрировать ошибку, а также, вероятно, повторно вызвать ее, чтобы по-прежнему завершать работу приложения». Можете ли вы продемонстрировать, как «вызвать» исключение, чтобы оно продолжало пузыриться даже после его перехвата? Мне кажется полезным добавить некоторые пользовательские сообщения об ошибках, в то же время позволяя исключению принудительно завершить работу приложения.
Габриэль Стейплс

1
Это помогает прояснить: они используют бланк except, но затем вызывают raiseбез аргументов, чтобы продолжить, чтобы исключение всплыло, завершив приложение. Мне это нравится: ianbicking.org/blog/2007/09/re-raising-exceptions.html . Похоже, твердое исключение из правила о неиспользовании одеяла except.
Габриэль Стейплс

1
@GabrielStaples Да, выловленное исключение может быть переброшено с помощью raise. Вы обычно делаете это только в нескольких местах в вашем приложении, чтобы зарегистрировать исключение.
совать

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

262

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

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

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


75

Выполнение вашего псевдокода буквально даже не дает никакой ошибки:

try:
    something
except:
    pass

как будто это совершенно правильный кусок кода, вместо того, чтобы бросать NameError. Я надеюсь, что это не то, что вы хотите.


51

Почему «кроме: пройти» плохая практика программирования?

Почему это плохо?

try:
    something
except:
    pass

Это перехватывает все возможные исключения, включая GeneratorExit, KeyboardInterruptи SystemExit- которые являются исключениями, которые вы, вероятно, не собираетесь перехватывать. Это так же, как ловить BaseException.

try:
    something
except BaseException:
    pass

Более старые версии документации гласят :

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

Исключительная иерархия Python

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

Вот иерархия исключений Python 3 - вы действительно хотите поймать их всех ?:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
           +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

Не делай этого

Если вы используете эту форму обработки исключений:

try:
    something
except: # don't just do a bare except!
    pass

Тогда вы не сможете прервать свой somethingблок с помощью Ctrl-C. Ваша программа пропустит все возможные исключения внутри tryблока кода.

Вот еще один пример, который будет иметь такое же нежелательное поведение:

except BaseException as e: # don't do this either - same as bare!
    logging.info(e)

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

try:
    foo = operation_that_includes_int(foo)
except ValueError as e:
    if fatal_condition(): # You can raise the exception if it's bad,
        logging.info(e)   # but if it's fatal every time,
        raise             # you probably should just not catch it.
    else:                 # Only catch exceptions you are prepared to handle.
        foo = 0           # Here we simply assign foo to 0 and continue. 

Дальнейшее объяснение с другим примером

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

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

Благодаря более точной обработке ошибок ваш код может быть более надежным.


31
>>> import this

Дзен Питона, Тим Питерс

Красиво лучше, чем безобразно.
Явное лучше, чем неявное.
Простое лучше, чем сложное.
Сложный лучше, чем сложный.
Квартира лучше, чем вложенная.
Разреженный лучше, чем плотный.
Читаемость имеет значение.
Особые случаи не достаточно особенные, чтобы нарушать правила.
Хотя практичность превосходит чистоту.
Ошибки никогда не должны проходить бесшумно.
Если явно не молчать.
Перед лицом двусмысленности откажитесь от соблазна гадать.
Должен быть один - и желательно только один - очевидный способ сделать это.
Хотя этот путь поначалу может быть неочевидным, если вы не голландец.
Сейчас лучше, чем никогда.
Хотя никогда не бывает лучше, чемпрямо сейчас
если реализацию сложно объяснить, это плохая идея.
Если реализацию легко объяснить, это может быть хорошей идеей.
Пространства имен - одна из отличных идей - давайте сделаем больше!

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


64
-1 Аргумент от власти на самом деле ничего не объясняет . Власть может ошибаться.
Изката

23
то, что написал @Izkata, И, на одну строку ниже, тот же самый авторитет пишет: «Если явно не молчать», что и есть, за исключением: pass делает.
Офри Равив

13
@OfriRaviv Нет, ошибка не проходит неявно ? В явном виде потребовалось бы назвать ошибку, которая должна пройти бесшумно, то есть явно об этом . Это не то, что, кроме: пройти делает.
Chelonian

24

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

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


13

Во-первых, он нарушает два принципа Zen of Python :

  • Явное лучше, чем неявное
  • Ошибки никогда не должны проходить бесшумно

Это означает, что вы намеренно делаете свою ошибку молча. Более того, вы не знаете, какая именно ошибка произошла, потому чтоexcept: pass что поймает любое исключение.

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

try:
    something
except:
    logger.exception('Something happened')

Но, как правило, если вы пытаетесь поймать какое-либо исключение, вы, вероятно, делаете что-то не так!


2
... Если явно не молчать, как в случае с OP.
Гиперборей

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

2
@ Hyperboreus, я не думаю, что перехват всех и любых ошибок явно заставляет их замолчать, то есть вы даже не знаете, что вы ловите.
Александр Жуков

13
«Потому что какой-то парень так говорит», на самом деле это не ответ на вопрос «почему?» вопрос.
Себастьян Неграсус

12

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

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

Что делает это особенно важным в Python, так это то, что по идиомам этого языка исключения не обязательно являются ошибками . Конечно, они часто используются таким же образом, как и в большинстве языков. Но, в частности, Python иногда использовал их для реализации альтернативного пути выхода из некоторых задач кода, который на самом деле не является частью обычного работающего случая, но все же известно, что время от времени он возникает и может даже ожидаться в большинстве случаев. SystemExitуже упоминалось в качестве старого примера, но наиболее распространенным примером в настоящее время может быть StopIteration. Использование исключений таким образом вызвало много споров, особенно когда итераторы и генераторы были впервые представлены в Python, но в итоге идея возобладала.


12

Причина № 1 уже была указана - она ​​скрывает ошибки, которые вы не ожидали.

(# 2) - Это делает ваш код трудным для чтения и понимания другими. Если вы перехватываете FileNotFoundException при попытке прочитать файл, то для другого разработчика будет совершенно очевидно, какой функциональностью должен обладать блок «catch». Если вы не укажете исключение, вам понадобятся дополнительные комментарии, чтобы объяснить, что должен делать блок.

(# 3) - Это демонстрирует ленивое программирование. Если вы используете универсальный try / catch, это указывает либо на то, что вы не понимаете возможных ошибок времени выполнения в вашей программе, либо на том, что вы не знаете, какие исключения возможны в Python. Поймание конкретной ошибки показывает, что вы понимаете и вашу программу, и диапазон ошибок, которые выдает Python. Это, скорее всего, заставит других разработчиков и рецензентов доверять вашей работе.


12

Итак, что выводит этот код?

fruits = [ 'apple', 'pear', 'carrot', 'banana' ]

found = False
try:
     for i in range(len(fruit)):
         if fruits[i] == 'apple':
             found = true
except:
     pass

if found:
    print "Found an apple"
else:
    print "No apples in list"

Теперь представьте try- exceptблок сотня строк звонков в сложную иерархию объектов, и сам называются в середине вызова дерева большой программы. Когда программа идет не так, где вы начинаете искать?


5
Э-э, спасибо людям, которые «исправили» это, но, пожалуйста, не делайте - это намеренно неправильно, в смысле «вопроса об интервью». Возможно, это более тонко, чем кажется на первый взгляд - попробуйте. Я хочу сказать, что сжатие исключений «все», особенно в Python, затрудняет отладку даже в тривиальной строке кода.
Ян Харви

11

В общем, вы можете классифицировать любую ошибку / исключение в одной из трех категорий :

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

  • Boneheaded : Ваша собственная ошибка, скорее всего, из-за недосмотра, ошибки или ошибки программирования. Вы должны исправить ошибку. Опять же, вы, безусловно, не должны игнорировать и продолжать.

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

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


6

Проще говоря, если выдается исключение или ошибка, что-то не так. Это может быть не совсем неправильно, но создавать, выдавать и перехватывать ошибки и исключения только ради использования операторов goto не очень хорошая идея, и это делается редко. 99% времени где-то была проблема.

Проблемы должны быть решены. Также как в жизни, в программировании, если вы просто оставляете проблемы в покое и стараетесь их игнорировать, они не просто уходят сами по себе много раз; вместо этого они становятся больше и размножаются. Чтобы предотвратить возникновение проблемы и дальнейшее нанесение ударов по дороге, вы либо: 1) устраняете ее и впоследствии убираете беспорядок, либо 2) сдерживаете ее, а затем убираете беспорядок.

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

В редких случаях проблема настолько незначительна, тривиальна и - помимо необходимости в блоке try ... catch - самодостаточна , что на самом деле после этого просто нет беспорядка, который нужно убрать. Это единственный случай, когда эта лучшая практика не обязательно применяется. По моему опыту, это, как правило, означало, что то, что делает код, в основном мелкое и податливое, и что-то вроде попыток повторения или специальных сообщений не стоит ни сложности, ни удержания потока.

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


6

На мой взгляд, у ошибок есть причина, по которой я звучу глупо, но так оно и есть. Хорошее программирование вызывает ошибки только тогда, когда вам приходится с ними справляться. Кроме того, как я читал некоторое время назад, «pass-Statement - это оператор, который показывает, что код будет вставлен позже», поэтому, если вы хотите, чтобы пустой оператор извлечения был пустым, не стесняйтесь, но для хорошей программы найдется быть частью пропавшего. потому что вы не справляетесь с вещами, которые должны иметь. Появляющиеся исключения дают вам возможность исправить входные данные или изменить структуру данных, чтобы эти исключения не возникали снова (но в большинстве случаев (исключения сети (Общие исключения ввода)) указывают, что следующие части программы не будут работать должным образом. Например, исключение NetworkException может указывать на разорванное сетевое соединение, и программа не может отправлять / получать данные на следующих этапах программы.

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

try:
    #code here
except Error1:
    #exception handle1

except Error2:
    #exception handle2
#and so on

можно переписать так:

try:
    #code here
except BaseException as e:
    if isinstance(e, Error1):
        #exception handle1

    elif isinstance(e, Error2):
        #exception handle2

    ...

    else:
        raise

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


4

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

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

Другим примером идиотской первостепенной важности является использование gotoоператора. Когда я учился в школе, наш профессор научил нас, gotoоператора, просто упомянуть, что ты не будешь использовать его, НИКОГДА. Не верьте людям, говорящим вам, что xyz никогда не следует использовать, и не может быть сценария, когда он полезен. Там всегда есть.


1
Случай «goto» является стилистическим и вызывает мнение, тогда как «исключение: пройти» обычно фактически неверно. Предполагается, что если кто-то, например, «убьет -TERM» вашего процесса в этот момент, он должен игнорировать его. По крайней мере, это плохое поведение.
Score_Under

1
@Score_Under еще есть случаи, когда это целесообразно использовать. Например, когда функция, которую вы вызываете, является дополнительной, неизвестного происхождения / автора, это не влияет на основные функции, но если сбой может вызвать проблемы. Я действительно понимаю, что вы утверждаете, что такие вызовы должны быть должным образом исследованы и проанализированы, но в реальной жизни это не всегда возможно.
Галец

Тем не менее, если я хочу завершить ваш процесс, kill -9 не должен быть единственным надежным вариантом.
Score_Under

2

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


2

Поскольку это еще не было упомянуто, лучше использовать стиль contextlib.suppress:

with suppress(FileNotFoundError):
    os.remove('somefile.tmp')

Обратите внимание, что в представленном примере состояние программы остается неизменным, независимо от того, происходит ли исключение. То есть somefile.tmpвсегда становится несуществующим.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.