Чому "крім: пройти" є поганою практикою програмування?


324

Я часто бачу коментарі до інших запитань щодо переповнення стека про те, як використання цього except: passзасобу не рекомендується. Чому це погано? Іноді мені просто байдуже, які помилки є, і я хочу просто продовжити код.

try:
    something
except:
    pass

Чому використання except: passблоку погано? Що робить це погано? Це факт, що я passна помилку, або що я exceptпомилка?


1
Щонайменше, я б запропонував вам записати його, щоб ви знали, які проблеми ви ігноруєте. Використовуйте loggingмодуль на рівні DEBUG, щоб уникнути їх виведення у виробництво, але тримати їх доступними в розвитку.
pcurry

Відповіді:


346

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

Моє пояснення "трохи" довше - тому tl; dr воно розпадається на це:

  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
Msgstr "Ви хоч хочете ввійти до помилки, а також, ймовірно, перейміть її, щоб все-таки припинити програму". Чи можете ви продемонструвати, як "переробити" виняток, щоб він продовжував кипіти навіть після того, як його спіймали? Мені здається корисним додавати до деяких користувацьких повідомлень про помилки, залишаючи, що виняток змушує програму вийти.
Габріель

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

1
@GabrielStaples Так, спійманий виняток можна скинути за допомогою raise. Зазвичай ви робите це лише в декількох місцях у вашій програмі, щоб записати виняток.
ткнути

Це чудово, уникайте пропускання, крім блоків. Я б сказав, що робити все, що здається більш зрозумілим, особливо іншим. Отримайте другий набір очей пітона, щоб переглянути свій код і побачити, чи не ставлять вони під сумнів блок. Читання є ключовим.
radtek

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. 

Подальше пояснення з іншим прикладом

Ви можете це робити, тому що ви перебираєте веб-сайт і отримуєте сказане, UnicodeErrorа тому, що ви використовували найширший вилов винятків, ваш код, який може мати інші основні недоліки, спробує запустити до завершення, витрачаючи пропускну здатність. , час обробки, зношування обладнання, втрата пам’яті, збір даних про сміття тощо.

Якщо інші люди просять вас заповнити так, щоб вони могли покластися на ваш код, я розумію, що вимушені просто впоратись із усім. Але якщо ви будете готові шумно виходити з ладу, у вас буде можливість виправити проблеми, які можуть виникати лише з перервами, але це буде довгостроково дорогими помилками.

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


31
>>> import this

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

Красиве краще, ніж потворне.
Явне краще, ніж неявне.
Простий - краще, ніж складний.
Комплекс краще, ніж складний.
Квартира краще, ніж вкладена.
Розріджений краще, ніж щільний.
Читання рахується.
Особливі випадки недостатньо спеціальні для порушення правил.
Хоча практичність перемагає чистоту.
Помилки ніколи не повинні проходити мовчки.
Якщо явно мовчати.
В умовах неоднозначності відмовтеся від спокуси здогадатися.
Повинно бути один - і бажано лише один - очевидний спосіб це зробити.
Хоча спочатку цей спосіб може бути не очевидним, якщо ви нідерландці.
Зараз краще, ніж ніколи.
Хоча ніколи не буває краще, ніж кращепрямо зараз.
Якщо реалізацію важко пояснити, це погана ідея.
Якщо реалізацію легко пояснити, це може бути хорошою ідеєю.
Простори імен - це чудова ідея - давайте зробимо більше таких!

Отже, ось моя думка. Щоразу, коли ви знайдете помилку, вам слід щось зробити для її усунення, тобто записати її в логінфайл чи щось інше. Принаймні, він повідомляє вам, що раніше була помилка.


64
-1 Аргументи влади фактично нічого не пояснюють . Авторитет може помилятися.
Ізката

23
те, що написав @Izkata, І, один рядок під ним, той самий авторитет пише: "Якщо явно не замовчується", це саме те, що виключає: pass.
Офрі Равів

13
@OfriRaviv Ні, чи не помилка проходить неявно ? Явно вимагатиме назвати помилку, яка повинна пройти мовчки, тобто бути явною щодо неї . Це не що, крім: пас робить.
Челоніан

24

Ви повинні використовувати принаймні, except Exception:щоб уникнути винятків системних винятків, таких як SystemExitабо KeyboardInterrupt. Ось посилання на документи.

Загалом слід чітко визначити винятки, які ви хочете зловити, щоб уникнути небажаних винятків. Ви повинні знати, які винятки ви ігноруєте .


13

По-перше, він порушує два принципи дзен-пітона :

  • Явне краще, ніж неявне
  • Помилки ніколи не повинні проходити мовчки

Це означає, що ви навмисно змушуєте свою помилку пройти мовчки. Більше того, ви не знаєте, яка саме помилка сталася, тому що except: passвипаде будь-який виняток.

По-друге, якщо ми спробуємо абстрагуватися від дзен Питона і говорити в термін справедливої ​​розумності, ви повинні знати, що використання не except:passзалишає вас ніяких знань і контролю у вашій системі. Основне правило - створити виняток, якщо помилка трапиться, та вжити відповідних дій. Якщо ви не знаєте заздалегідь, якими вони повинні бути, принаймні занотуйте помилку десь (і краще повторно підняти виняток):

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

Але, як правило, якщо ви намагаєтеся зловити якийсь виняток, ви, мабуть, робите щось не так!


2
... Якщо явно не замовчується, що стосується ОП.
Гіперборей

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

2
@Hyperboreus, я не думаю, що ловлі всіх та будь-яких помилок явно замовчують їх, тобто ви навіть не знаєте, що ви ловите.
Олександр Жуков

13
"Тому що якийсь хлопець так говорить" насправді не є відповіддю на запитання "Чому?" питання.
Себастьян Неграш

12

except:passКонструкція істотно заглушає будь-які виняткові умови , які приходять в той час як код розглядається в try:блоці біжать.

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

Що робить це особливо важливим у Python, це те, що за ідіомами цієї мови винятки не обов'язково є помилками . Звичайно, вони часто використовуються таким чином, як і в більшості мов. Але Python, зокрема, періодично використовував їх для реалізації альтернативного шляху виходу з деяких завдань коду, які насправді не є частиною звичайного запущеного випадку, але, як відомо, час від часу з'являються і навіть у більшості випадків їх можна очікувати. SystemExitвже згадувався як старий приклад, але найпоширенішим прикладом на сьогодні може бути StopIteration. Використання винятків таким чином викликало багато суперечок, особливо коли ітератори та генератори вперше були представлені Python, але з часом ідея переважала.


12

Причина №1 вже вказана - вона приховує помилки, яких ви не очікували.

(# 2) - Це робить ваш код важким для читання та розуміння інших. Якщо ви ловите FileNotFoundException, коли ви намагаєтесь прочитати файл, тоді іншому розробнику досить очевидно, якою функціональністю повинен володіти блок 'catch'. Якщо ви не вказали виняток, тоді вам потрібно додаткове коментування, щоб пояснити, що повинен робити блок.

(# 3) - Це демонструє ліниве програмування. Якщо ви використовуєте загальну спробу / ловити, це вказує або на те, що ви не розумієте можливих помилок під час виконання програми, або що не знаєте, які винятки можливі в 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

Загалом, ви можете класифікувати будь-яку помилку / виняток в одній з трьох категорій :

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

  • Бездоганний : ваша власна вина, швидше за все, через нагляд, помилку чи помилку програмування. Ви повинні виправити помилку. Знову ж таки, вам, звичайно, не слід ігнорувати і продовжувати.

  • Екзогенні : Ви можете очікувати цих помилок у виняткових ситуаціях, таких як файл не знайдено або з'єднання припинено . Ви повинні чітко обробляти ці помилки, і лише ці.

У всіх випадках except: passви залишаєте програму лише в невідомому стані, де вона може завдати більше шкоди.


6

Простіше кажучи, якщо викид або помилка кидається, щось не так. Це може бути не дуже помилково, але створювати, кидати та фіксувати помилки та винятки лише заради використання goto-операторів - це не дуже гарна ідея, і це рідко робиться. 99% часу десь була проблема.

Проблеми потрібно вирішувати. Як і в житті, і в програмуванні, якщо ви просто залишаєте проблеми в спокої і намагаєтесь їх ігнорувати, вони не просто йдуть багато разів самостійно; натомість вони збільшуються і розмножуються. Щоб запобігти зростанню проблеми на вас і знову вдарити далі по дорозі, ви або 1) усуньте її і очистіть після цього безлад, або 2) утримуйте його та очистіть безлад після цього.

Просто ігнорувати винятки та помилки та залишати їх таким, як хороший спосіб випробувати витоки пам'яті, видатні підключення до бази даних, непотрібні блокування дозволів на файли тощо.

У рідкісних випадках проблема настільки мізерна, тривіальна, і - окрім необхідності спробувати ... блок лову - автономний , що насправді просто не треба безладно прибирати згодом. Це єдині випадки, коли ця найкраща практика не обов'язково застосовується. З мого досвіду, це, як правило, означає, що те, що робиться в коді, є в основному дрібним і недозволеним, і щось на кшталт спроб повторних спроб або спеціальних повідомлень не вартує ні складності, ні утримування нитки.

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


6

На мою думку, помилки мають привід здатися, що мій звук дурний, але це так. Хороше програмування викликає помилки лише тоді, коли вам доведеться їх обробляти. Крім того, як я читав деякий час тому, "пропуск-заява - це заява, що показ коду буде вставлено пізніше", тому якщо ви хочете мати порожню, окрім заяви, сміливо це робіть, але для хорошої програми бути частиною відсутньої. тому що ти не справляєшся з речами, які ти повинен мати. Винятки, що виникають, дають вам можливість виправити вхідні дані або змінити структуру даних, щоб ці винятки не виникали повторно (але в більшості випадків (виключення з мережі, загальні вхідні винятки) вказують на те, що наступні частини програми не виконуються добре. Наприклад, NetworkException може вказувати на розрив мережевого з'єднання і програма не може надсилати / отримувати дані в наступних кроках програми.

Але використання блоку пропуску лише для одного блоку виконання є дійсним, оскільки ви все ще розрізняєте типи винятків, тому якщо ви помістите всі блоки винятків в один, він не порожній:

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

Тож навіть декілька, крім блоків з операторами пропуску, можуть призвести до коду, структура якого обробляє особливі типи винятків.


4

Усі підготовлені до цього часу коментарі є дійсними. По можливості вам потрібно вказати, який саме виняток ви хочете проігнорувати. По можливості вам потрібно проаналізувати, що спричинило виняток, і ігнорувати лише те, що ви хотіли ігнорувати, а не інше. Якщо виняток призводить до того, що додаток "аварійно виходить з ладу", то, будь-то так, адже набагато важливіше знати несподіване, що сталося, коли воно сталося, ніж приховувати, що проблема коли-небудь виникала.

З урахуванням сказаного, не приймайте будь-яку практику програмування як першорядну роль. Це нерозумно. Завжди є час і місце для блокування ігнорування всіх винятків.

Іншим прикладом ідіотичного першочергового значення є використання gotoоператора. Коли я навчався в школі, наш професор навчив нас gotoоператора, щоб згадати, що ти його не будеш використовувати, ВСЕ. Не вірте людям, які говорять вам про те, що xyz ніколи не слід використовувати і не може бути сценарію, коли він корисний. Завжди є.


1
Випадок "goto" є стилістичним і викликає думку, тоді як "крім: pass" зазвичай фактично неправильно. Він передбачає, що якщо хтось, наприклад, "вбив -TERM" ваш процес в цей момент, він повинен ігнорувати його. Принаймні, це погана поведінка.
Score_Under

1
@Score_Поки не все, є випадки, коли це доцільно використовувати. Наприклад, коли функція, яку ви викликаєте, є додатковою, невідомого походження / автора, не впливає на функціональність ядра, але якщо збої можуть спричинити проблеми. Я усвідомлюю, що ви можете стверджувати, що подібні дзвінки повинні бути належним чином досліджені та проаналізовані, але в реальному житті це не завжди можливо.
Галети

Однак, якщо я хочу припинити ваш процес, 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.