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

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

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

try:
    shutil.rmtree(path)
except:
    pass

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: заявление. Опять же, почему?

не указывая исключения catches исключения, в том числе 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 to if e.errno == errno.ENOENT:


когда вы просто хотите сделать try catch без обработки исключения, как вы это делаете в 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

и вот автор, Рэймонд Хеттингер, говорит об этом и всех видах другой горячности Python: 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 учебник.

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

>>> 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 context manager:

from contextlib import suppress

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

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

вы будете молча игнорировать 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 это правильный способ получить утверждение, которое не-op. Но когда вы делаете голый 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 

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

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

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

...

reg, Tilokchan


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