Как правильно игнорировать исключения


когда вы просто хотите попробовать-кроме как без обработки исключения, как вы это делаете в Python?

следующий правильный способ сделать это?

try:
    shutil.rmtree(path)
except:
    pass
11 618

11 ответов:

try:
  doSomething()
except: 
  pass

или

try:
  doSomething()
except Exception: 
  pass

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

обычно считается лучшей практикой ловить только те ошибки, которые вас интересуют. В случае shutil.rmtree наверное OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

если вы хотите молча игнорировать эту ошибку, вы бы сделали:

try:
    shutil.rmtree(path)
except OSError:
    pass

почему? Скажем, вы (как-то) случайно передаете функцию целое число вместо строки, например:

shutil.rmtree(2)

это даст ошибку "TypeError: принуждение к Unicode: нужна строка или буфер, int найден" - вы вероятно, не хочу игнорировать это, что может быть трудно отладить.

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

не указывая исключение ловит исключения, в том числе SystemExit исключение, которое, например,sys.exit() применение:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

сравните это со следующим, который правильно выходит:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

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

try:
    shutil.rmtree(path)
except OSError, e:
    if e.errno == 2:
        # suppress "No such file or directory" error
        pass
    else:
        # reraise the exception, as it's an unexpected error
        raise

вы могли бы также import errno, и if до if e.errno == errno.ENOENT:

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

Это зависит от того, что вы подразумеваете под "обработкой."

Если вы хотите поймать его без каких-либо действий, код, который вы опубликовали, будет работать.

Если вы имеете в виду, что вы хотите принять меры по исключению, не останавливая исключение от перехода в стек, то вы хотите что-то вроде этого:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

сначала я цитирую ответ Джека о'Коннора из этой теме. Ссылочный поток закрылся, поэтому я пишу здесь:

" есть новый способ сделать это в Python 3.4:

from contextlib import suppress

with suppress(Exception):
    # your code

вот фиксация, которая добавила его:http://hg.python.org/cpython/rev/406b47c64480

и вот автор, Раймонд Хеттингер, говорит об этом и всяких других горячих питонах: https://youtu.be/OSGv2VnC0go?t=43m23s

мое дополнение к этому-эквивалент Python 2.7:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

тогда вы используете его, как в Python 3.4:

with ignored(Exception):
    # your code

комплектность:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"

...из python tutorial.

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

>>> try:
...     this_fails()
... except ZeroDivisionError as detail:
...     print 'Handling run-time error:', detail

Как правильно игнорировать исключения?

есть несколько способов сделать это.

однако выбор примера имеет простое решение, которое не охватывает общий случай.

конкретный пример:

вместо

try:
    shutil.rmtree(path)
except:
    pass

этого:

shutil.rmtree(path, ignore_errors=True)

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

>>> import shutil
>>> help(shutil.rmtree)

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

общий подход

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

новое в Python 3.4:

вы можете импортировать suppress контекстный менеджер:

from contextlib import suppress

но только подавить наиболее конкретное исключение:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

вы будете молча игнорировать a FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

С docs:

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

отметим, что suppress и FileNotFoundError доступны только в Python 3.

если вы хотите, чтобы ваш код также работал в Python 2, см. Следующий раздел:

Python 2 & 3:

когда вы просто хотите сделать попытку / за исключением без обработки исключения, как это сделать в Python?

следующий правильный способ сделать это?

try :
    shutil.rmtree ( path )
except :
    pass

для Python 2 совместимый код pass правильный способ иметь заявление о том, что не ОП. Но когда вы чуть-чуть except:, это то же самое, что делать except BaseException:, которая включает GeneratorExit,KeyboardInterrupt и SystemExit и вообще, вы не хотите, чтобы поймать этих вещей.

на самом деле, вы должны быть как можно конкретнее в именовании исключения, как вы можете.

вот часть Python (2) иерархия исключений, и как вы можете видеть, если вы поймаете более общие исключения, вы можете скрыть проблемы, которые вы сделали не ожидал:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

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

мы это конкретный номер ошибки из errno библиотека, и reraise, если у нас нет этого:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

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

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

@когда вы просто хотите сделать попытку поймать без обработки исключения, как вы это делаете в Python?

Это поможет вам напечатать, что такое исключение: (т. е. попробуйте поймать без обработки исключения и распечатать исключение.)

import sys
....
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]

...

reg, Тилокчан

try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

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

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

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

просто поднять соответствующее исключение, вот так:

try:
     raise NameError('Joan')
 except NameError:
     print 'An exception just raised again by Joan!'
     raise

вот так просто. :)

для получения более подробной информации, прочитайте эту документацию: https://docs.python.org/3.6/tutorial/errors.html

обработка исключения в Python: Если у вас есть какой-то подозрительный код, который может вызвать исключение, вы можете защитить свою программу, поместив подозрительный код в try: block.

try:
    # Your statements .............
except ExceptionI:
    # Your statements.............
except ExceptionII:
    # Your statements..............
else:
   # Your statements