How to properly ignore exceptions
当您只是想尝试—除非不处理异常,否则如何在Python中进行尝试?
下面的方法正确吗?
1 2 3 4 | try: shutil.rmtree(path) except: pass |
1 2 3 4 | try: doSomething() except: pass |
或
1 2 3 4 | try: doSomething() except Exception: pass |
不同之处在于,第一个捕获器还将捕获
通常认为最好的实践是只捕获您感兴趣的错误。在
1 2 3 4 | >>> shutil.rmtree("/fake/dir") Traceback (most recent call last): [...] OSError: [Errno 2] No such file or directory: '/fake/dir' |
如果你想悄悄地忽略这个错误,你可以这样做:
1 2 3 4 | try: shutil.rmtree(path) except OSError: pass |
为什么?假设您(以某种方式)意外地将一个整数而不是字符串传递给函数,比如:
1 | shutil.rmtree(2) |
它将给出错误"TypeError: cocing to Unicode: need string or buffer, int found"—您可能不想忽略这一点,这可能很难调试。
如果您确实想忽略所有错误,请捕获
不指定异常捕获每个异常,包括
1 2 3 4 5 6 | >>> try: ... sys.exit(1) ... except: ... pass ... >>> |
将其与下面正确退出的代码进行比较:
1 2 3 4 5 6 | >>> try: ... sys.exit(1) ... except Exception: ... pass ... shell:~$ |
如果你想写更好的行为代码,
1 2 3 4 5 6 7 8 9 | 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 |
您还可以将
When you just want to do a try catch without handling the exception, how do you do it in Python?
这取决于你所说的"处理"是什么意思。
如果您打算在不采取任何操作的情况下捕获它,那么您发布的代码将会工作。
如果你的意思是你想对异常采取行动,而不阻止异常上升堆栈,那么你想要这样的东西:
1 2 3 4 5 | try: do_something() except: handle_exception() raise #re-raise the exact same exception that was thrown |
首先,我从这篇文章中引用了杰克·奥康纳的答案。被引用的线程被关闭,所以我写在这里:
在Python 3.4中有一种新的方法可以做到这一点:
1 2 3 4 | from contextlib import suppress with suppress(Exception): # your code |
下面是添加它的commit: http://hg.python.org/cpython/rev/406b47c64480
这是作者Raymond Hettinger,他在讨论这个问题以及其他各种Python热:https://youtu.be/OSGv2VnC0go?t=43m23s
我添加的是Python 2.7的等效物:
1 2 3 4 5 6 7 8 | from contextlib import contextmanager @contextmanager def ignored(*exceptions): try: yield except exceptions: pass |
然后像在Python 3.4中那样使用它:
1 2 | with ignored(Exception): # your code |
完整性:
1 2 3 4 5 6 7 8 9 | >>> 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教程。
还请注意,您可以像这样捕获异常:
1 2 3 4 | >>> try: ... this_fails() ... except ZeroDivisionError as detail: ... print 'Handling run-time error:', detail |
How to properly ignore Exceptions?
有几种方法可以做到这一点。
然而,示例的选择有一个简单的解决方案,不涉及一般情况。
特定于示例:而不是
1 2 3 4 | try: shutil.rmtree(path) except: pass |
这样做:
1 | shutil.rmtree(path, ignore_errors=True) |
这是一个特定于
1 2 | >>> import shutil >>> help(shutil.rmtree) |
由于这只涵盖了示例的有限情况,所以我将进一步演示如何处理不存在这些关键字参数的情况。
一般方法
由于上面只讨论了示例的有限情况,所以我将进一步演示如何处理不存在这些关键字参数的情况。
New in python3.4:您可以导入
1 | from contextlib import suppress |
但只抑制最特殊的例外:
1 2 | with suppress(FileNotFoundError): shutil.rmtree(path) |
您将无声地忽略一个
1 2 3 4 | >>> with suppress(FileNotFoundError): ... shutil.rmtree('bajkjbkdlsjfljsf') ... >>> |
从文档:
As with any other mechanism that completely suppresses exceptions,
this context manager should be used only to cover very specific errors
where silently continuing with program execution is known to be the
right thing to do.
注意,
如果您希望您的代码也能在python2中工作,请参见下一节:
Python 2,3:
When you just want to do a try/except without handling the exception,
how do you do it in Python?Is the following the right way to do it?
1
2
3
4 try :
shutil.rmtree ( path )
except :
pass
对于Python 2兼容的代码,
事实上,在命名异常时应该尽可能地具体。
下面是Python(2)异常层次结构的一部分,正如您所看到的,如果您捕捉到更多的一般异常,您可以隐藏您没有预料到的问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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,可能您不关心的异常是是否没有目录。
我们可以从
1 2 3 4 5 6 7 8 9 | 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 |
注意,裸升会引发原始异常,在本例中,这可能正是您想要的。写得更简洁,因为我们真的不需要显式的
1 2 3 4 5 | try: shutil.rmtree(path) except OSError as error: if error.errno != errno.ENOENT: # no such file or directory raise |
When you just want to do a try catch without handling the exception,
how do you do it in Python?
这将帮助您打印异常是什么:(即在不处理异常的情况下尝试catch并打印异常)。
1 2 3 4 5 | import sys try: doSomething() except: print"Unexpected error:", sys.exc_info()[0] |
1 2 3 4 5 6 7 | try: doSomething() except Exception: pass else: stuffDoneIf() TryClauseSucceeds() |
仅供参考,else子句可以放在所有异常之后,并且只有在try中的代码没有引起异常时才会运行。
在Python中,我们处理与其他语言类似的异常,但是不同之处在于一些语法上的不同,例如,
1 2 3 4 5 6 7 8 | 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... |
我需要忽略多个命令中的错误,而fuckit做到了
1 2 3 4 5 6 7 8 9 10 11 | import fuckit @fuckit def helper(): print('before') 1/0 print('after1') 1/0 print('after2') helper() |
简单地提出相关的异常,就像这样:
1 2 3 4 5 | try: raise NameError('Joan') except NameError: print 'An exception just raised again by Joan!' raise |
就这么简单。:)
要了解更多细节,请阅读本文:https://docs.python.org/3.6/tutorial/errors.html