当你只想做一个 try-except 而不处理异常时,你如何在 Python 中做到这一点?
以下是正确的方法吗?
try:
shutil.rmtree(path)
except:
pass
shutil.rmtree(path, ignore_errors=True)
。但是,这不适用于大多数功能。
try:
doSomething()
except Exception:
pass
或者
try:
doSomething()
except:
pass
不同之处在于第二个也将捕获 KeyboardInterrupt
、SystemExit
和类似的东西,它们直接从 BaseException
派生,而不是 Exception
。
有关详细信息,请参阅文档:
尝试语句
例外
但是,捕获每个错误通常是不好的做法 - 请参阅 Why is "except: pass" a bad programming practice?
通常认为最佳做法是只捕获您感兴趣的错误。在 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: coercing to Unicode: need string or buffer, int found”——你可能不想忽略它,这可能很难调试。
如果您确实想忽略所有错误,请捕获 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
用于该功能。
Errno 2
到 errno.ENOENT
的。可能对很多人都有帮助。 ;) 有关详细信息,请参阅 Python Standard Errno System Symbols。
当你只想做一个 try catch 而不处理异常时,你如何在 Python 中做到这一点?
这取决于您所说的“处理”是什么意思。
如果您打算在不采取任何行动的情况下捕获它,那么您发布的代码将起作用。
如果你的意思是你想对异常采取行动而不阻止异常进入堆栈,那么你需要这样的东西:
try:
do_something()
except:
handle_exception()
raise #re-raise the exact same exception that was thrown
首先我引用 this thread 中 Jack o'Connor 的回答。引用的线程已关闭,所以我在这里写:
“在 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")
另请注意,您可以像这样捕获异常:
>>> 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:
i_might_fail()
except (ValueError, TypeError) as ex:
print('I failed with: ', ex)
...或作为单独的 except 子句:
try:
i_might_fail()
except ValueError:
print('handling a ValueError...')
except TypeError:
print('handling a TypeError...')
...见python tutorial。
如何正确忽略异常?
有几种方法可以做到这一点。
但是,示例的选择有一个简单的解决方案,不涵盖一般情况。
具体到例子:
代替
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 中工作,请参阅下一节:
蟒蛇 2 和 3:
当你只想做一个 try/except 而不处理异常时,你如何在 Python 中做到这一点?以下是正确的方法吗?尝试:shutil.rmtree(路径)除了:通过
对于 Python 2 兼容代码,pass
是获得无操作语句的正确方法。但是当你做一个简单的 except:
时,这与做 except BaseException:
包括 GeneratorExit
、KeyboardInterrupt
和 SystemExit
是一样的,一般来说,你不想抓住这些东西。
事实上,您应该尽可能具体地命名异常。
这是 Python (2) exception hierarchy 的一部分,如您所见,如果您捕获了更一般的异常,您可以隐藏您没有预料到的问题:
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
库中获取 that 特定的错误号,如果没有,则重新引发:
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
请注意,一个简单的 raise 会引发原始异常,这可能是您在这种情况下想要的。写得更简洁,因为我们真的不需要在异常处理中显式地 pass
使用代码:
try:
shutil.rmtree(path)
except OSError as error:
if error.errno != errno.ENOENT: # no such file or directory
raise
try:
doSomething()
except Exception:
pass
else:
stuffDoneIf()
TryClauseSucceeds()
仅供参考,else 子句可以跟踪所有异常,并且只有在 try 中的代码不会导致异常时才会运行。
else
进行了很好的解释。并且要补充一点,finally
将始终在任何(或无例外)之后运行。
我需要忽略多个命令中的错误,fuckit 成功了
import fuckit
@fuckit
def helper():
print('before')
1/0
print('after1')
1/0
print('after2')
helper()
当你只想做一个 try catch 而不处理异常时,你如何在 Python 中做到这一点?
这将帮助您打印异常是什么:(即在不处理异常的情况下尝试捕获并打印异常。)
import sys
try:
doSomething()
except:
print "Unexpected error:", sys.exc_info()[0]
在 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-except 而是另一种处理异常的方法,如果你喜欢面向对象编程的话:
class MyExceptionHandler:
def __enter__(self):
... # Do whatever when "with" block is started
return self
def __exit__(self, exc_type, exc_value, tb):
return True
然后到实际代码:
with MyExceptionHandler():
... # Code that may or may not raise an exception
shutil.rmtree(path)
这是如何工作的?
__enter__ 在进入 with 块时运行。
__exit__ 在退出 with 块时运行这应该返回 True 以使可能的异常静音。这应该返回 None (或被认为是 False 的东西)以不使潜在的异常静音。异常类型、实际异常及其回溯作为(位置)参数传递。您可以使用这些来确定要做什么。
这应该返回 True 以使可能的异常静音。
这应该返回 None (或被认为是 False 的东西)以不使潜在的异常静音。
异常类型、实际异常及其回溯作为(位置)参数传递。您可以使用这些来确定要做什么。
最后一点,更喜欢 try-except。如果您需要比平时更多的抽象,这可能很有用。
我通常只是这样做:
try:
doSomething()
except:
_ = ""
_ = ""
替换为 pass
。
_
,如果发生异常,那么在这个块之后,变量的值将会改变。
不定期副业成功案例分享
try: shuti.rmtree(...) except: pass
将粗略地抑制任何错误(即使您拼错shutil
导致NameError
) - 至少执行except OSError: