在Python中,特定的POSIX错误条件没有单独的异常类型 - 它们由OSError
异常对象内的属性区分。
让我们假设我正在执行文件操作(通过SFTP删除可能不存在的文件)并且我想忽略ENOENT,但仍然处理任何其他错误或异常。是否有可能比以下更优雅地做到这一点?
try:
action()
except OSError as e:
if e.errno == errno.ENOENT:
pass
else:
sophisticated_error_handling(e)
except e:
sophisticated_error_handling(e)
我不喜欢这种方法,因为它涉及重复。
注意:没有X-Y问题。 “action”是一个库函数,不能告诉它忽略ENOENT。
答案 0 :(得分:2)
实现相同结果的方法比您提出的代码更短,更惯用。
您可以尝试/捕获预期的错误,然后检查except子句中错误对象的条件。技巧是,如果错误对象不是您期望的特定子类型,则重新引发相同的错误对象。
import errno
try:
action()
except IOError as ioe:
if ioe.errno not in (errno.ENOENT,):
# this re-raises the same error object.
raise
pass # ENOENT. that line is optional, but it makes it look
# explicit and intentional to fall through the exception handler.
仅使用raise
(不带参数)重新引发初始错误很重要。您可能会被raise ioe
吸引而不是那条线上的raise
吸引。即使您保留相同的错误消息,但如果使用raise ioe
,它也会使错误的堆栈跟踪看起来就像错误发生在该行中一样,而不是在错误发生的action()
内部。>
在您建议的代码中,即使您的第二个异常处理程序在语法上有效,也不会触发它。您必须指定except e
或except <type>:
。
如果您要进行其他复杂的错误处理,以确保正确性,则可以将所有以前的try / catch嵌套在外部except <type> as <variable>:
/ try
中:
except
当嵌套这样的异常处理程序时,您要注意的一件事是,异常处理程序也可以引发异常。 here文档中有一个有关异常处理的教程,但是您可能会发现它有点密集。
方法2
如果您喜欢meta-python技巧,则可以考虑使用with statement的方法。您可以创建一个能够吸收特定类型错误的python上下文管理器。
try:
try:
action()
except IOError as ioe:
if ioe.errno not in (errno.ENOENT,): raise
except IOError as any_other_ioerror:
# this is reached in case you get other errno values
sophisticated_error_handling()
except OtherExceptionTypeICareAbout as other:
other_fancy_handler()
然后您可以编写简单的代码,例如:
# add this to your utilities
class absorb(object):
def __init__(self, *codes):
self.codes = codes
def __exit__(self, exc_type, value, traceback):
if hasattr(value, "errno") and getattr(value, "errno") in self.codes:
return True # exception is suppressed
return False # exception is re-raised
def __enter__(self):
return None
如果您仍然希望针对其他errno情况进行复杂的错误处理,则可以将上述内容包含在try / except中,如下所示:
# if ENOENT occurs during the block, abort the block, but do not raise.
with absorb(errno.ENOENT):
delete_my_file_whether_it_exists_or_not()
print("file deleted.") # reachable only if previous call returned
注意:您可能还想看看contextlib,它可能会为您消除一些元缺陷。
答案 1 :(得分:-1)
接下来只需输入错误类型即可!
test = [1, 2, 3, 4, 5, 6, 'aasd']
for i in range(50):
try:
print(test[i])
except IndexError:
pass