尝试/在Python除外:你如何正确地忽略例外?
当你只是想做一个尝试 – 除非没有处理exception,你怎么在Python中做到这一点?
下面是正确的做法吗?
try: shutil.rmtree(path) except: pass
try: doSomething() except: pass
要么
try: doSomething() except Exception: pass
不同的是,第一个也会捕获KeyboardInterrupt
, SystemExit
和类似的东西,这些是直接从exceptions.BaseException
,而不是exceptions.Exception
。
详细信息请参阅文档:
当你只想做一个try catch而不处理这个exception时,你如何在Python中做到这一点?
这取决于你的意思是“处理”。
如果你的意思是在不采取任何行动的情况下抓住它,你发布的代码将会起作用。
如果你的意思是你想对一个exception采取行动,而不是停止堆栈上的exception,那么你需要这样的东西:
try: do_something() except: handle_exception() raise #re-raise the exact same exception that was thrown
通常认为最好的做法是只捕获你感兴趣的错误。对于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
为什么? 说你(不知何故)意外地传递一个整数,而不是一个string,如:
shutil.rmtree(2)
它会给出错误“TypeError:胁迫到Unicode:需要string或缓冲区,findint” – 你可能不想忽略,这可能很难debugging。
如果您肯定要忽略所有错误,请捕获Exception
而不是纯粹的except:
语句。 再一次,为什么?
不指定exception捕获每个exception,包括例如sys.exit()
使用的SystemExit
exception:
>>> try: ... sys.exit(1) ... except: ... pass ... >>>
将其与以下正确的退出相比较:
>>> try: ... sys.exit(1) ... except Exception: ... pass ... shell:~$
如果你想写更好的行为代码, OSError
exception可以代表各种错误,但在上面的例子中,我们只想忽略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:
首先,我引用Jack o'Connor的回答。 被引用的线程被closures,所以我写在这里:
“Python 3.4中有一个新的方法:
from contextlib import suppress with suppress(Exception): # your code
这是添加它的提交: http : //hg.python.org/cpython/rev/406b47c64480
这里的作者Raymond Hettinger谈论了这个以及各种其他的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教程 。
另外请注意,您可以捕获像这样的exception:
>>> try: ... this_fails() ... except ZeroDivisionError as detail: ... print 'Handling run-time error:', detail
如何正确地忽略exception?
有几种方法可以做到这一点。
然而,例子的select有一个简单的解决scheme,不包括一般情况。
具体到这个例子:
代替
try: shutil.rmtree(path) except: pass
做这个:
shutil.rmtree(path, ignore_errors=True)
这是shutil.rmtree
特有的一个参数。 您可以通过执行以下操作来查看它的帮助,而且您会发现它也可以允许错误的function。
>>> import shutil >>> help(shutil.rmtree)
由于这只涵盖了这个例子的狭义范例,如果这些关键字参数不存在,我将进一步演示如何处理这个问题。
一般方法
由于上面只覆盖了范例的狭义范例,我将进一步演示如果这些关键字参数不存在,如何处理这个问题。
Python 3.4新增function:
您可以导入suppress
上下文pipe理器:
from contextlib import suppress
但是只能抑制最具体的例外:
with suppress(FileNotFoundError): shutil.rmtree(path)
你会默默地忽略一个FileNotFoundError
:
>>> with suppress(FileNotFoundError): ... shutil.rmtree('bajkjbkdlsjfljsf') ... >>>
从文档 :
与其他任何完全抑制exception的机制一样,这个上下文pipe理器应该只用于覆盖非常具体的错误,在那里默默继续执行程序是正确的。
请注意, suppress
和FileNotFoundError
仅在Python 3中可用。
如果你想让你的代码在Python 2中工作,请参阅下一节:
Python 2&3:
当你只是想做一个尝试/除了没有处理exception,你怎么在Python中做到这一点?
下面是正确的做法吗?
try : shutil.rmtree ( path ) except : pass
对于Python 2兼容的代码, pass
是一个没有操作的语句的正确方法。 但是,当你做一个裸露的except:
,就像except BaseException:
它包括GeneratorExit
, KeyboardInterrupt
和SystemExit
,一般来说,你不想捕捉这些东西。
事实上,你应该尽可能的在命名exception方面具体。
以下是Python(2) exception层次结构的一部分,正如您所看到的,如果您捕捉到更一般的exception,则可以隐藏您并不期望的问题:
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,也许你不在乎的exception是没有目录。
我们可以从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
请注意,裸举会引起原来的exception,这可能是你想要的。 写得更简洁,因为我们并不需要在exception处理中显式pass
代码:
try: shutil.rmtree(path) except OSError as error: if error.errno != errno.ENOENT: # no such file or directory raise
@当你只想做一个try catch而不处理这个exception时,你如何在Python中做到这一点?
这将帮助你打印什么exception是:(即尝试赶上没有处理exception和打印exception。)
导入系统 .... 尝试: 做一点事() 除: 打印“意外的错误:”,sys.exc_info()[0] ...
reg,Tilokchan
try: doSomething() except Exception: pass else: stuffDoneIf() TryClauseSucceeds()
FYI else子句可以在所有exception之后执行,只有在try中的代码不会导致exception时才会运行。
在Python中,我们处理类似于其他语言的exception,但差异是一些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..
在python中处理exception:如果你有一些可能引发exception的可疑代码,你可以通过将可疑代码放在try:区块中来防御你的程序。
try: # your statements ............. except ExceptionI: # your statments............. except ExceptionII: # your statments.............. else: # your statments