Как правильно игнорировать исключения - PullRequest
679 голосов
/ 08 апреля 2009

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

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

try:
    shutil.rmtree(path)
except:
    pass

Ответы [ 11 ]

935 голосов
/ 08 апреля 2009
try:
  doSomething()
except: 
  pass

или

try:
  doSomething()
except Exception: 
  pass

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

125 голосов
/ 10 апреля 2009

Как правило, рекомендуется отлавливать только те ошибки, которые вас интересуют. В случае 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)

Это выдаст ошибку "Ошибка типа: приведение к 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:

109 голосов
/ 08 апреля 2009

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

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

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

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

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown
78 голосов
/ 08 сентября 2013

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

"В 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
54 голосов
/ 06 марта 2010

Для полноты:

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

... из учебника по питону .

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

>>> try:
...     this_fails()
... except ZeroDivisionError as detail:
...     print 'Handling run-time error:', detail
41 голосов
/ 22 января 2015

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

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

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

Специфично для примера:

Вместо

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)

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

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

Из документов :

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

Обратите внимание, что 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 и повысить его, если у нас его нет:

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 
12 голосов
/ 12 октября 2011

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

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

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]
9 голосов
/ 20 ноября 2009
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

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

3 голосов
/ 18 ноября 2010

В 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...
1 голос
/ 02 декабря 2018

Мне нужно было игнорировать ошибки в нескольких командах, и fuckit добился цели

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()
...