Коли ви просто хочете зробити спробу, за винятком випадків, не обробляючи виняток, як це зробити в Python?
Чи є наступним правильним способом це зробити?
try:
shutil.rmtree(path)
except:
pass
Коли ви просто хочете зробити спробу, за винятком випадків, не обробляючи виняток, як це зробити в Python?
Чи є наступним правильним способом це зробити?
try:
shutil.rmtree(path)
except:
pass
Відповіді:
try:
doSomething()
except:
pass
або
try:
doSomething()
except Exception:
pass
Різниця полягає в тому, що перший також буде ловити KeyboardInterrupt
, SystemExit
і подібні речі, які виводяться безпосередньо з exceptions.BaseException
, а не exceptions.Exception
.
Детальну інформацію див. У документації:
try: shuti.rmtree(...) except: pass
буде жорстоко придушити будь-які помилки (навіть якщо ви неправильно shutil
NameError
except OSError:
Як правило, найкращою практикою вважається лише помилка, яка вас цікавить. 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
, щоб ми могли бути ще більш конкретними:
import errno
try:
shutil.rmtree(path)
except OSError as e:
if e.errno != errno.ENOENT:
# ignore "No such file or directory", but re-raise other errors
raise
shutil.rmtree
не найкращий приклад, тому що ви просто використали б ignore_errors=True
для цієї функції ..
Коли ви просто хочете зробити спробу лову, не обробляючи виняток, як це зробити в Python?
Це залежить від того, що ви маєте на увазі під "поводженням".
Якщо ви хочете зловити його, не вживаючи жодних дій, код, який ви опублікували, спрацює.
Якщо ви хочете сказати, що ви хочете вжити заходів за винятком, не зупиняючи виняток на підйом стека, то вам потрібно щось подібне:
try:
do_something()
except:
handle_exception()
raise #re-raise the exact same exception that was thrown
Спочатку я цитую відповідь Джека o'Connor з цієї теми . Посилальна нитка закрилася, і я пишу тут:
"У 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")
Також зауважте, що ви можете зафіксувати такий виняток:
>>> try:
... this_fails()
... except ZeroDivisionError as err:
... print("Handling run-time error:", err)
... і знову підняти такий виняток:
>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
... raise
... приклади з підручника пітона .
Як правильно ігнорувати винятки?
Існує кілька способів зробити це.
Однак вибір прикладу має просте рішення, яке не охоплює загального випадку.
Замість
try:
shutil.rmtree(path)
except:
pass
Зробити це:
shutil.rmtree(path, ignore_errors=True)
Це специфічний аргумент shutil.rmtree
. Ви можете побачити довідку в ній, виконавши наступне, і ви побачите, що вона також може враховувати функціональність і при помилках.
>>> import shutil
>>> help(shutil.rmtree)
Оскільки це стосується лише вузького випадку прикладу, я далі продемонструю, як впоратися з цим, якщо ці аргументи ключового слова не існували.
Оскільки вищезазначене стосується лише вузького випадку прикладу, я далі продемонструю, як це впоратися, якщо цих аргументів ключового слова не існувало.
Ви можете імпортувати 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?
Чи є наступним правильним способом це зробити?
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
Коли ви просто хочете зробити спробу лову, не обробляючи виняток, як це зробити в Python?
Це допоможе вам роздрукувати, що таке виняток :( тобто спробуйте catch, не обробляючи виняток, і надрукуйте виняток.)
import sys
try:
doSomething()
except:
print "Unexpected error:", sys.exc_info()[0]
try:
doSomething()
except Exception:
pass
else:
stuffDoneIf()
TryClauseSucceeds()
FYI, інше застереження може виконуватись після всіх винятків і запускатиметься лише в тому випадку, якщо код у спробі не викликає винятку.
else
цього контексту. І додати, що завждиfinally
буде працювати після будь-якого (або без винятку).
Мені потрібно було ігнорувати помилки в декількох командах і fuckit зробив свою справу
import fuckit
@fuckit
def helper():
print('before')
1/0
print('after1')
1/0
print('after2')
helper()
У 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:
doSomething()
except:
_ = ""
_ = ""
на pass
.
shutil.rmtree(path, ignore_errors=True)
. Однак це не стосується більшості функцій.