else
声明的可选try
子句的用途是什么?
答案 0 :(得分:750)
else
块中的语句如果执行落在try
的底部,则执行 - 如果没有异常。老实说,我从来没有找到过需要。
然而,Handling Exceptions注意到:
使用else子句更好 而不是添加额外的代码到try 条款,因为它意外地避免 抓住一个不是的例外 由受到保护的代码引发的 试试......除了陈述。
所以,如果你有一个方法可以,例如,抛出一个IOError
,你想要捕获它引发的异常,但是如果第一个操作成功,你还想做其他事情,而你< em>不想要从该操作中捕获IOError,您可以编写如下内容:
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()
如果你只是在another_operation_that_can_throw_ioerror()
之后加operation_that_can_throw_ioerror
,那么except
会抓住第二个来电的错误。如果你把它放在整个try
块之后,它将一直运行,直到finally
之后。 else
可让您确定
finally
块之前运行,IOError
都没有被抓到答案 1 :(得分:86)
使用else
时有一个大的原因 - 风格和可读性。保留代码可以在代码处理它们附近引起异常通常是一个好主意。例如,比较这些:
try:
from EasyDialogs import AskPassword
# 20 other lines
getpass = AskPassword
except ImportError:
getpass = default_getpass
和
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
else:
# 20 other lines
getpass = AskPassword
当except
无法提前返回或重新抛出异常时,第二个是好的。如果可能的话,我会写:
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
return False # or throw Exception('something more descriptive')
# 20 other lines
getpass = AskPassword
注意:从最近发布的重复here复制的答案,因此所有这些“AskPassword”内容。
答案 2 :(得分:45)
一个用途:测试一些应引发异常的代码。
try:
this_should_raise_TypeError()
except TypeError:
pass
except:
assert False, "Raised the wrong exception type"
else:
assert False, "Didn't raise any exception"
(此代码应在实践中抽象为更通用的测试。)
答案 3 :(得分:34)
Python try-else
try语句的可选
else
子句的用途是什么?
如果没有例外,并且else
,return
或continue
语句没有中断,break
语句就会运行。
如果控件流出,则执行可选的
else
子句try
子句的结束。*
(Bolding补充道。)脚注上写着:
*目前,控制“流出结束”除外 异常或执行
return
,continue
或break
声明。
它确实需要至少一个前面的except子句(see the grammar)。所以它真的不是“尝试其他”,它是“尝试 - 除了 - 否定( - 最终)”,else
(和finally
)是可选的。
Python Tutorial详细说明了预期用途:
try ... except语句有一个可选的else子句,当时 礼物,必须遵循除了条款以外的所有条款它对代码很有用 如果try子句没有引发异常,则必须执行。对于 例如:
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()
使用else子句比添加其他代码要好 try子句,因为它避免意外捕获异常 这个代码不受try的保护而引发...除外 言。
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!
答案 4 :(得分:16)
Try-except-else非常适合将the EAFP pattern与duck-typing结合使用:
try:
cs = x.cleanupSet
except AttributeError:
pass
else:
for v in cs:
v.cleanup()
你可能认为这个天真的代码很好:
try:
for v in x.cleanupSet:
v.clenaup()
except AttributeError:
pass
这是在代码中意外隐藏严重错误的好方法。我在那里进行了错误的清理,但是让我知道的AttributeError被吞没了。更糟糕的是,如果我写得正确怎么办,但是清理方法偶尔会传递一个具有错误名称属性的用户类型,导致它在中途无声地失败并保持文件未闭合?祝你好好调试一下。
答案 5 :(得分:14)
我发现即使有例外,你必须要做清理才真的有用:
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()
答案 6 :(得分:10)
即使您现在无法想到它的使用,您也可以打赌必须使用它。这是一个缺乏想象力的样本:
使用else
:
a = [1,2,3]
try:
something = a[2]
except:
print "out of bounds"
else:
print something
没有else
:
try:
something = a[2]
except:
print "out of bounds"
if "something" in locals():
print something
如果没有抛出错误,您可以在此处定义变量something
。您可以在try
块之外删除它,但如果定义了变量,则需要进行一些混乱的检测。
答案 7 :(得分:8)
来自Errors and Exceptions # Handling exceptions - docs.python.org
try ... except
语句有一个可选的else
子句, 在场的时候,必须遵循所有除了条款。它对代码很有用 如果try子句没有引发异常,则必须执行该操作。 例如: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()
使用else子句比添加其他代码要好 try子句,因为它避免意外捕获异常 这个代码不受try的保护而引发...除外 言。
答案 8 :(得分:6)
PEP 380中有try-else
的好例子。基本上,它归结为在算法的不同部分进行不同的异常处理。
这是这样的:
try:
do_init_stuff()
except:
handle_init_suff_execption()
else:
try:
do_middle_stuff()
except:
handle_middle_stuff_exception()
这允许您编写更接近异常发生位置的异常处理代码。
答案 9 :(得分:5)
查看Python reference似乎else
在try
之后执行时没有异常。
如果控制流出try子句的末尾,则执行可选的else子句。 2 else子句中的异常不由前面的except子句处理。
Dive into python有一个例子,如果我理解正确的话,在try
块中他们会尝试导入一个模块,当失败时你得到异常并绑定默认值但是当它工作时你可以选择进入else
块并绑定所需内容(请参阅示例和说明的链接)。
如果你试图在catch
块中工作,它可能会抛出另一个异常 - 我想这就是else
块可以派上用场的地方。
答案 10 :(得分:3)
大多数答案似乎都集中在为什么我们不能将材料放在try子句本身的else子句中。问题else clause in try statement... what is it good for特别询问为什么else子句代码不能在 try块本身之后,并且该问题被重复到这个问题,但我在这里看不到对该问题的明确答复。我觉得https://stackoverflow.com/a/3996378/1503120出色地回答了这个问题。我还试图在https://stackoverflow.com/a/22579805/1503120阐明各种条款的各种重要性。
答案 11 :(得分:3)
就是这样。 try-except子句的'else'块存在于尝试的操作成功时(且仅当)尝试运行的代码。它可以使用,也可以被滥用。
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
就个人而言,我喜欢并在适当的时候使用它。它在语义上对语句进行分组。
答案 12 :(得分:2)
也许用途可能是:
#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()
也许这会让你过度使用。
答案 13 :(得分:1)
这是另一个我喜欢使用这种模式的地方:
while data in items:
try
data = json.loads(data)
except ValueError as e:
log error
else:
# work on the `data`
答案 14 :(得分:1)
我发现else
对于处理可能不正确的配置文件非常有用:
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
读取lock
配置的异常会禁用锁定监控,而ValueErrors会记录一条有用的警告消息。
答案 15 :(得分:1)
通常可以存在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.
"""
在这种情况下,在每个除了块之外设置inconsistency_type
,以便在else
中的无错误情况下补充该行为。
当然,我将此描述为一种模式,有一天可能会出现在您自己的代码中。在这种特定情况下,您只需在inconsistency_type
块之前将try
设置为0。
答案 16 :(得分:1)
我发现try: ... else:
构造在运行数据库查询并将这些查询的结果记录到具有相同flavor / type的单独数据库的情况下非常有用。假设我有很多工作线程都处理提交到队列的数据库查询
#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
当然,如果您可以区分可能引发的异常,则不必使用它,但如果代码对成功的代码做出反应可能会抛出与成功代码相同的异常,那么您可以不要让第二个可能的例外,或者在成功时立即返回(这会在我的情况下杀死线程),然后这确实派上用场了。
答案 17 :(得分:1)
假设您的编程逻辑取决于字典是否具有给定键的条目。您可以使用dict.get(key)
构造测试if... else...
的结果,或者您可以执行以下操作:
try:
val = dic[key]
except KeyError:
do_some_stuff()
else:
do_some_stuff_with_val(val)
答案 18 :(得分:1)
我能想到的其中一个使用场景是不可预测的异常,如果再试一次可以绕过这些异常。例如,当try块中的操作涉及随机数时:
while True:
try:
r = random.random()
some_operation_that_fails_for_specific_r(r)
except Exception:
continue
else:
break
但是如果可以预测异常,则应始终事先选择验证异常。但是,并非所有内容都可以预测,因此这种代码模式就有了它的位置。
答案 19 :(得分:1)
try:
statements # statements that can raise exceptions
except:
statements # statements that will be executed to handle exceptions
else:
statements # statements that will be executed if there is no exception
示例:
try:
age=int(input('Enter your age: '))
except:
print ('You have entered an invalid value.')
else:
if age <= 21:
print('You are not allowed to enter, you are too young.')
else:
print('Welcome, you are old enough.')
输出:
>>>
Enter your age: a
You have entered an invalid value.
>>> RESTART
>>>
Enter your age: 25
Welcome, you are old enough.
>>>RESTART
>>>
Enter your age: 13
You are not allowed to enter, you are too young.
>>>
复制自:https://geek-university.com/python/the-try-except-else-statements/
答案 20 :(得分:0)
我将添加另一个在处理数据库会话时似乎很简单的用例:
# getting a DB connection
conn = db.engine.connect()
# and binding to a DB session
session = db.get_session(bind=conn)
try:
# we build the query to DB
q = session.query(MyTable).filter(MyTable.col1 == 'query_val')
# i.e retrieve one row
data_set = q.one_or_none()
# return results
return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]
except:
# here we make sure to rollback the transaction,
# handy when we update stuff into DB
session.rollback()
raise
else:
# when no errors then we can commit DB changes
session.commit()
finally:
# and finally we can close the session
session.close()
答案 21 :(得分:-16)
else:
区块令人困惑,而且(几乎)无用。它也是for
和while
语句的一部分。
实际上,即使在if
语句中,else:
也可能以非常糟糕的方式被滥用,从而产生很难找到的错误。
考虑一下。
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
对else:
三思而后行。这通常是个问题。除了if
- 语句之外,请避免使用它,甚至考虑记录else
- 条件以使其明确。