尝试/在Python除外:你如何正确地忽略例外?

当你只是想做一个尝试 – 除非没有处理exception,你怎么在Python中做到这一点?

下面是正确的做法吗?

try: shutil.rmtree(path) except: pass 
 try: doSomething() except: pass 

要么

 try: doSomething() except Exception: pass 

不同的是,第一个也会捕获KeyboardInterruptSystemExit和类似的东西,这些是直接从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()使用的SystemExitexception:

 >>> try: ... sys.exit(1) ... except: ... pass ... >>> 

将其与以下正确的退出相比较:

 >>> try: ... sys.exit(1) ... except Exception: ... pass ... shell:~$ 

如果你想写更好的行为代码, OSErrorexception可以代表各种错误,但在上面的例子中,我们只想忽略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理器应该只用于覆盖非常具体的错误,在那里默默继续执行程序是正确的。

请注意, suppressFileNotFoundError仅在Python 3中可用。

如果你想让你的代码在Python 2中工作,请参阅下一节:

Python 2&3:

当你只是想做一个尝试/除了没有处理exception,你怎么在Python中做到这一点?

下面是正确的做法吗?

 try : shutil.rmtree ( path ) except : pass 

对于Python 2兼容的代码, pass是一个没有操作的语句的正确方法。 但是,当你做一个裸露的except: ,就像except BaseException:它包括GeneratorExitKeyboardInterruptSystemExit ,一般来说,你不想捕捉这些东西。

事实上,你应该尽可能的在命名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