Python try-else
如果执行从
但是,处理异常注意事项:
The use of the else clause is better
than adding additional code to the try
clause because it avoids accidentally
catching an exception that wasn’t
raised by the code being protected by
the try ... except statement.
因此,如果您有一个方法可以,例如,抛出一个
1 2 3 4 5 6 7 8 9 | try: operation_that_can_throw_ioerror() except IOError: handle_the_exception_somehow() else: # we don't want to catch the IOError if it's raised another_operation_that_can_throw_ioerror() finally: something_we_always_need_to_do() |
如果你把
使用
1 2 3 4 5 6 | try: from EasyDialogs import AskPassword # 20 other lines getpass = AskPassword except ImportError: getpass = default_getpass |
和
1 2 3 4 5 6 7 | try: from EasyDialogs import AskPassword except ImportError: getpass = default_getpass else: # 20 other lines getpass = AskPassword |
当
1 2 3 4 5 6 7 8 | try: from EasyDialogs import AskPassword except ImportError: getpass = default_getpass return False # or throw Exception('something more descriptive') # 20 other lines getpass = AskPassword |
注意:答案是从最近发布的副本复制过来的,因此所有这些"askpassword"的东西。
一种用法:测试一些应该引发异常的代码。
1 2 3 4 5 6 7 8 | try: this_should_raise_TypeError() except TypeError: pass except: assert False,"Raised the wrong exception type" else: assert False,"Didn't raise any exception" |
(该代码应该在实践中抽象为更通用的测试。)
Python try-else
What is the intended use of the optional
else clause of the try statement?
总结
如果没有异常,并且没有被
来自文档:
The optional
else clause is executed if and when control flows off the
end of thetry clause.*
(加上粗体)脚注如下:
*Currently, control"flows off the end" except in the case of an
exception or the execution of areturn ,continue , orbreak statement.
它至少需要一个前导的except子句(参见语法)。因此,它实际上不是"尝试其他",而是"尝试其他"(最后),因为
python教程详细介绍了预期的用法:
The try ... except statement has an optional else clause, which, when
present, must follow all except clauses. It is useful for code that
must be executed if the try clause does not raise an exception. For
example:
1
2
3
4
5
6
7
8 for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()The use of the else clause is better than adding additional code to
the try clause because it avoids accidentally catching an exception
that wasn’t raised by the code being protected by the try ... except
statement.
区分
如果处理错误,则不会运行
1 2 3 4 5 6 7 8 | def handle_error(): try: raise RuntimeError('oops!') except RuntimeError as error: print('handled a RuntimeError, no big deal.') else: print('if this prints, we had no error!') # won't print! print('And now we have left the try block!') # will print! |
现在,
1 2 3 | >>> handle_error() handled a RuntimeError, no big deal. And now we have left the try block! |
Try except else非常适合将EAFP模式与duck类型相结合:
1 2 3 4 5 6 7 | try: cs = x.cleanupSet except AttributeError: pass else: for v in cs: v.cleanup() |
你可能会这么认为吗?VE代码很好:
1 2 3 4 5 | try: for v in x.cleanupSet: v.clenaup() except AttributeError: pass |
这是在代码中意外隐藏严重错误的好方法。我在那里输入了"清理",但会让我知道的属性错误被吞噬了。更糟糕的是,如果我正确地编写了它,但是清理方法偶尔会被传递给一个具有错误命名属性的用户类型,导致它在中途默默地失败并使文件保持未关闭状态呢?祝你调试的时候好运。
我发现当你有清理工作要做的时候它真的很有用,即使有例外:
1 2 3 4 5 6 7 8 | try: data = something_that_can_go_wrong() except Exception as e: # yes, I know that's a bad way to do it... handle_exception(e) else: do_stuff(data) finally: clean_up() |
即使你现在想不出它的用途,你也可以打赌一定有它的用途。这是一个缺乏想象力的样本:
使用
1 2 3 4 5 6 7 | a = [1,2,3] try: something = a[2] except: print"out of bounds" else: print something |
无
1 2 3 4 5 6 7 | try: something = a[2] except: print"out of bounds" if"something" in locals(): print something |
这里定义了变量
来自错误和异常处理异常-docs.python.org
The
try ... except statement has an optionalelse clause, which,
when present, must follow all except clauses. It is useful for code
that must be executed if the try clause does not raise an exception.
For example:
1
2
3
4
5
6
7
8 for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()The use of the else clause is better than adding additional code to
the try clause because it avoids accidentally catching an exception
that wasn’t raised by the code being protected by the try ... except
statement.
在PEP 380中有一个很好的
就像这样:
1 2 3 4 5 6 7 8 9 | try: do_init_stuff() except: handle_init_suff_execption() else: try: do_middle_stuff() except: handle_middle_stuff_exception() |
这允许您编写更接近异常发生位置的异常处理代码。
从python引用来看,似乎
深入到python有一个例子,如果我理解正确,在
如果您试图在
大多数答案似乎集中在为什么我们不能把材料放在try子句本身的else子句中。try语句中的question else子句…为什么else子句代码不能跟踪try块本身,而这个问题被复制到这个问题上,这有什么好处,但是我在这里没有看到对这个问题的明确答复。我觉得https://stackoverflow.com/a/3996378/1503120很好地回答了这个问题。我还试图在https://stackoverflow.com/a/22579805/1503120中阐明各种条款的各种意义。
就是这样。try except子句的"else"块适用于在(并且仅当)尝试的操作成功时运行的代码。它可以被使用,也可以被滥用。
1 2 3 4 5 6 7 8 9 10 | try: fp= open("configuration_file","rb") except EnvironmentError: confdata= '' # it's ok if the file can't be opened else: confdata= fp.read() fp.close() # your code continues here # working with (possibly empty) confdata |
就我个人而言,我喜欢它,并在适当的时候使用它。它在语义上对语句进行分组。
也许一个用途是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #debug = [] def debuglog(text, obj=None): " Simple little logger." try: debug # does global exist? except NameError: pass # if not, don't even bother displaying except: print('Unknown cause. Debug debuglog().') else: # debug does exist. # Now test if you want to log this debug message # from caller"obj" try: if obj in debug: print(text) # stdout except TypeError: print('The global"debug" flag should be an iterable.') except: print('Unknown cause. Debug debuglog().') def myfunc(): debuglog('Made it to myfunc()', myfunc) debug = [myfunc,] myfunc() |
也许这也会让你发挥作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | try: test_consistency(valuable_data) except Except1: inconsistency_type = 1 except Except2: inconsistency_type = 2 except: # Something else is wrong raise else: inconsistency_type = 0 """ Process each individual inconsistency down here instead of inside the except blocks. Use 0 to mean no inconsistency. """ |
在这种情况下,除了块外,每个块中都设置了
当然,我将此描述为一种模式,有一天可能会出现在您自己的代码中。在这种特定情况下,您只需在
我能想到的一个使用场景是不可预知的异常,如果您再试一次,就可以绕过这些异常。例如,当try块中的操作涉及随机数时:
1 2 3 4 5 6 7 8 | while True: try: r = random.random() some_operation_that_fails_for_specific_r(r) except Exception: continue else: break |
但是如果可以预测异常,那么您应该总是事先选择验证而不是异常。然而,并不是所有的事情都可以预测,所以这个代码模式有它的位置。
我发现
1 2 3 4 5 6 7 | try: value, unit = cfg['lock'].split() except ValueError: msg = 'lock monitoring config must consist of two words separated by white space' self.log('warn', msg) else: # get on with lock monitoring if config is ok |
读取
我发现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #in a long running loop try: query = queue.get() conn = connect_to_db(<main db>) curs = conn.cursor() try: curs.execute("<some query on user input that may fail even if sanitized">) except DBError: logconn = connect_to_db(<logging db>) logcurs = logconn.cursor() logcurs.execute("<update in DB log with record of failed query") logcurs.close() logconn.close() else: #we can't put this in main try block because an error connecting #to the logging DB would be indistinguishable from an error in #the mainquery #We can't put this after the whole try: except: finally: block #because then we don't know if the query was successful or not logconn = connect_to_db(<logging db>) logcurs = logconn.cursor() logcurs.execute("<update in DB log with record of successful query") logcurs.close() logconn.close() #do something in response to successful query except DBError: #This DBError is because of a problem with the logging database, but #we can't let that crash the whole thread over what might be a #temporary network glitch finally: curs.close() conn.close() #other cleanup if necessary like telling the queue the task is finished |
当然,如果您能够区分可能引发的异常,您就不必使用它,但是如果对一段成功代码做出反应的代码可能会抛出与成功代码相同的异常,那么您就不能让第二个可能的异常消失,或者在成功后立即返回(这会杀死我的CA中的线程)。SE),这确实很有用。
假设您的编程逻辑取决于字典是否有带有给定键的条目。您可以使用
1 2 3 4 5 6 | try: val = dic[key] except KeyError: do_some_stuff() else: do_some_stuff_with_val() |
这里是另一个我喜欢使用这种模式的地方:
1 2 3 4 5 6 7 | while data in items: try data = json.loads(data) except ValueError as e: log error else: # work on the `data` |
事实上,即使是在
考虑一下这个。
1 2 3 4 5 6 7 | if a < 10: # condition stated explicitly elif a > 10 and b < 10: # condition confusing but at least explicit else: # Exactly what is true here? # Can be hard to reason out what condition is true |
再想一想