python - ylabel - 如何正確地忽略異常?
python title position (7)
當你只想做一個嘗試 - 除了沒有處理異常之外,你怎麼在Python中做到這一點?
以下是正確的做法嗎?
try:
shutil.rmtree(path)
except:
pass
如何正確地忽略異常?
有幾種方法可以做到這一點。
然而,例子的選擇有一個簡單的解決方案,不包括一般情況。
具體到這個例子:
代替
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')
...
>>>
從docs :
和其他任何完全抑制異常的機制一樣,這個上下文管理器應該只用於覆蓋非常具體的錯誤,在那裡默默地繼續執行程序是正確的。
請注意, suppress
和FileNotFoundError
僅在Python 3中可用。
如果你希望你的代碼在Python 2中工作,請參閱下一節:
Python 2&3:
當你只是想做一個嘗試/除非沒有處理異常,你如何在Python中做到這一點?
以下是正確的做法嗎?
try : shutil.rmtree ( path ) except : pass
對於Python 2兼容的代碼來說, pass
是一個正確的方式來讓一個沒有操作的語句。 但是當你做一個except:
...... except:
,這與except BaseException:
的操作相同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
當你只想做一個try catch而不處理異常時,你如何在Python中做到這一點?
這取決於你的意思是“處理”。
如果你的意思是在沒有採取任何行動的情況下抓住它,你發布的代碼將會起作用。
如果你的意思是你想對異常採取行動而不會停止堆棧上的異常,那麼你需要這樣的東西:
try:
do_something()
except:
handle_exception()
raise #re-raise the exact same exception that was thrown
在python中處理異常:如果您有一些可能引發異常的可疑代碼,您可以通過將可疑代碼放置在try:區塊中來維護您的程序。
try:
# your statements .............
except ExceptionI:
# your statments.............
except ExceptionII:
# your statments..............
else:
# your statments
在python中,我們處理類似於其他語言的異常,但差異在於某些syntex差異,例如 -
try:
#Your Code in which exception can occur
except <here we can put particular exception name>:
#we can call that exception here also, like ZeroDivisionError()
#now your code
#we can put finally block also
finally:
#YOur Code..
通常認為最好的做法是只捕獲你感興趣的錯誤。對於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:
語句。 同樣,為什麼?
不指定異常會捕獲每個異常,包括例如sys.exit()
使用的SystemExit
異常:
>>> 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 3.4中提供了一種新的方法:
from contextlib import suppress
with suppress(Exception):
# your code
以下是添加它的提交: http://hg.python.org/cpython/rev/406b47c64480 : http://hg.python.org/cpython/rev/406b47c64480
下面是作者Raymond Hettinger談論這個以及各種其他Python熱點: https://youtu.be/OSGv2VnC0go?t=43m23s ://youtu.be/OSGv2VnC0go https://youtu.be/OSGv2VnC0go?t=43m23s t https://youtu.be/OSGv2VnC0go?t=43m23s 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
try:
doSomething()
except:
pass
要么
try:
doSomething()
except Exception:
pass
不同之處在於,第一個也會捕獲KeyboardInterrupt
, SystemExit
等類似的東西,它們直接來自exceptions.BaseException
,而不是exceptions.Exception
。
詳情請參閱文檔: