try语句的可选else子句的预期用途是什么?
当前回答
使用else样式和可读性是一个重要原因。将可能导致异常的代码放在处理异常的代码附近通常是个好主意。例如,比较这些:
try:
from EasyDialogs import AskPassword
# 20 other lines
getpass = AskPassword
except ImportError:
getpass = default_getpass
and
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
else:
# 20 other lines
getpass = AskPassword
当异常不能提前返回或重新抛出异常时,第二个方法很好。如果可能的话,我会这样写:
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
return False # or throw Exception('something more descriptive')
# 20 other lines
getpass = AskPassword
注意:答案从最近发布的副本复制在这里,因此所有这些“AskPassword”的东西。
其他回答
我能想到的一种使用场景是不可预测的异常,如果您再次尝试,可以避免这种异常。例如,当try块中的操作涉及随机数时:
while True:
try:
r = random.random()
some_operation_that_fails_for_specific_r(r)
except Exception:
continue
else:
break
但是如果可以预测异常,则应该始终在异常之前选择验证。然而,并不是所有的事情都可以预测,所以这种代码模式有它的一席之地。
else块通常可以用来补充出现在每个except块中的功能。
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.
"""
在这种情况下,在每个except块中设置inconsistency_type,以便在无错误情况下在else中补充行为。
当然,我将此描述为某一天可能会出现在您自己的代码中的模式。在这个特定的情况下,您只要在try块之前将inconsistency_type设置为0即可。
一种用法:测试一些应该引发异常的代码。
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 try语句的可选else子句的预期用途是什么?
其预期用途是,如果没有预期要处理的异常,则为运行更多代码提供上下文。
这个上下文避免意外处理您没有预料到的错误。
但是理解导致else子句运行的确切条件非常重要,因为return、continue和break可以中断到else的控制流。
总之
如果没有异常,并且没有被return、continue或break语句中断,else语句将运行。
其他答案忽略了最后一部分。
从文档中可以看出:
类型的控件流出时,执行可选的else子句 try子句结束
(粗体)。脚注写道:
*目前,控制“从末端流出”,除非在 异常或return、continue或break语句的执行。
它至少需要一个except子句(参见语法)。所以它实际上不是“try-else”,而是“try-except-else(-finally)”,其中else(和finally)是可选的。
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: 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.
示例区分else和try块后面的代码
如果处理错误,else块将不会运行。例如:
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!
现在,
>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!
我已经找到了…Else:在运行数据库查询并将这些查询的结果记录到相同风格/类型的单独数据库的情况下,构造非常有用。假设我有很多工作线程,它们都处理提交给队列的数据库查询
#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
当然,如果您能够区分可能抛出的异常,则不必使用这种方法,但是如果代码对成功的代码段的响应可能会抛出与成功的代码段相同的异常,并且您不能让第二个可能的异常消失,或者在成功时立即返回(在我的例子中,这会杀死线程),那么这种方法就会派上用场。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录