Python 中“try”语句的可选“else”子句的预期用途是什么?
- 2024-12-30 08:42:00
- admin 原创
- 101
问题描述:
else
该语句的可选子句的预期用途是什么try
?
解决方案 1:
else
如果执行超出了底部,则执行块中的语句try
- 如果没有异常。老实说,我从未发现过这种需要。
但是,处理异常指出:
使用 else 子句比在 try 子句中添加额外的代码更好,因为它可以避免意外捕获未由 try ... except 语句保护的代码引发的异常。
因此,如果您有一个方法,例如,可以抛出一个IOError
,并且您想要捕获它引发的异常,但是如果第一个操作成功,您还想做其他事情,并且您不想从该操作中捕获 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
问题都不会在这里得到解决
解决方案 2:
使用它的一个重要原因是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
注意:答案是从这里最近发布的重复内容中复制而来的,因此都是“AskPassword”的内容。
解决方案 3:
Python try-else
else
try 语句的可选子句的预期用途是什么?
预期用途是,如果没有预期处理的异常,则拥有一个可以运行更多代码的上下文。
这种上下文可以避免意外处理您未预料到的错误。
但了解导致 else 子句运行的确切条件非常重要,因为return
、continue
和break
可能会中断到 的控制流else
。
总之
如果没有异常并且没有被、或语句打断,该else
语句就会运行。return
`continue`break
其他答案忽略了最后一部分。
来自文档:
else
当控制流出子句的末尾时,将执行可选子句try
。*
(粗体添加。)脚注如下:
*目前,除了出现异常或执行
return
、continue
或break
语句的情况外,控制“会从末尾流出”。
它确实需要至少一个前置 except 子句(参见语法)。因此,它实际上不是“try-else”,而是“try-except-else(-finally)”,其中else
(and finally
) 是可选的。
Python 教程详细阐述了其预期用途:
try ... except 语句有一个可选的 else 子句,如果存在,则必须跟在所有 except 子句之后。它对于在 try 子句未引发异常时必须执行的代码很有用。例如:
for arg in sys.argv[1:]: try: f = open(arg, 'r') except OSError: print('cannot open', arg) else: print(arg, 'has', len(f.readlines()), 'lines') f.close()
使用 else 子句比在 try 子句中添加额外的代码更好,因为它可以避免意外捕获未由 try ... except 语句保护的代码引发的异常。
区分块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:
一种用途:测试一些应该引发异常的代码。
try:
this_should_raise_TypeError()
except TypeError:
pass
except:
assert False, "Raised the wrong exception type"
else:
assert False, "Didn't raise any exception"
(在实践中,应该将此代码抽象为更通用的测试。)
解决方案 5:
Try-except-else 非常适合将EAFP 模式与duck-typing结合起来:
try:
cs = x.cleanupSet
except AttributeError:
pass
else:
for v in cs:
v.cleanup()
你可能会认为这个简单的代码还不错:
try:
for v in x.cleanupSet:
v.clenaup() # <-- deliberate typo
except AttributeError:
pass
这是意外隐藏代码中严重错误的好方法。我在那里打错了cleanup
,但那个AttributeError
会让我明白的被吞掉了。更糟糕的是,如果我写得正确,但清理方法偶尔会传递一个具有错误命名属性的用户类型,导致它在中途默默失败并留下一个未关闭的文件,那该怎么办?祝你好运调试那个。
解决方案 6:
我发现当你需要进行清理工作时它非常有用,即使出现异常也必须完成:
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()
解决方案 7:
即使你现在想不出它的用途,但你可以肯定它一定有用。这是一个缺乏想象力的示例:
和else
:
a = [1,2,3]
try:
something = a[2]
except IndexError:
print("out of bounds")
else:
print(something)
没有else
:
try:
something = a[2]
except IndexError:
print("out of bounds")
if "something" in locals():
print(something)
这里something
定义了一个变量,如果没有抛出错误的话。你可以从try
块外移除它,但如果定义了一个变量,那么就需要进行一些混乱的检测。
解决方案 8:
PEP 380try-else
中有一个很好的例子。基本上,它归结为在算法的不同部分进行不同的异常处理。
它是这样的:
try:
do_init_stuff()
except:
handle_init_suff_execption()
else:
try:
do_middle_stuff()
except:
handle_middle_stuff_exception()
这使得你可以在更接近异常发生的位置编写异常处理代码。
解决方案 9:
来自错误和异常 # 处理异常 - docs.python.org
该
try ... except
语句有一个可选else
子句,如果存在,则必须跟在所有 except 子句之后。它对于在 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 ... except 语句保护的代码引发的异常。
解决方案 10:
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/
解决方案 11:
查看Python 参考资料,似乎else
在没有异常时执行try
。当控制流出 try 子句的末尾时,将执行可选的 else 子句。2 else子句中的异常不由前面的 except 子句处理。
深入研究 python有一个例子,如果我理解正确的话,在try
块中他们尝试导入一个模块,当失败时你会得到异常并绑定默认值,但是当它工作时你可以选择进入else
块并绑定所需的内容(请参阅链接以获取示例和解释)。
如果您尝试在catch
块中执行工作,它可能会引发另一个异常 - 我猜这就是else
块派上用场的地方。
解决方案 12:
就是这样。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
我个人很喜欢它,并在适当的时候使用它。它对语句进行语义分组。
解决方案 13:
我将添加另一个在处理数据库会话时看起来很简单的用例:
# 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()
解决方案 14:
我发现这种try: ... 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
当然,如果您可以区分可能引发的异常,则不必使用它,但如果对成功的代码做出反应的代码可能会引发与成功代码相同的异常,并且您不能只放过第二个可能的异常,或者在成功时立即返回(在我的情况下这会杀死线程),那么这确实很方便。
解决方案 15:
也许用途如下:
#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()
也许这也会给你带来用处。
解决方案 16:
这是我喜欢使用此模式的另一个地方:
while data in items:
try
data = json.loads(data)
except ValueError as e:
log error
else:
# work on the `data`
解决方案 17:
一个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
在每个 except 块中设置,以便在无错误情况下补充行为else
。
当然,我将其描述为将来可能出现在您自己的代码中的一种模式。在这个特定情况下,您无论如何都要在块inconsistency_type
之前将其设置为 0 try
。
解决方案 18:
我能想到的一个使用场景是不可预知的异常,通过重试可以规避这些异常。例如,当 try 块中的操作涉及随机数时:
while True:
try:
r = random.random()
some_operation_that_fails_for_specific_r(r)
except Exception:
continue
else:
break
但是如果可以预测异常,您应该始终选择事先进行验证而不是异常。然而,并非所有事情都可以预测,因此此代码模式有其适用之处。
解决方案 19:
我发现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 会记录一条有用的警告消息。
解决方案 20:
dict.get(key)
假设你的编程逻辑取决于字典中是否有给定键的条目。你可以使用构造来测试结果if... else...
,也可以执行以下操作:
try:
val = dic[key]
except KeyError:
do_some_stuff()
else:
do_some_stuff_with_val(val)
解决方案 21:
可以使用此构造在finally
子句中以常见的方式处理异常,而当没有异常时执行其他操作:
class TooManyRetries(RuntimeError):
pass
n_tries = 0
max_retries = 2
while True:
try:
n_tries += 1
if n_tries >= max_retries:
raise TooManyRetries
fail_prone_operation()
except Exception1 as ex:
# handle1
except Exception2 as ex:
# handle2
except Exception3 as ex:
# handle3
except TooManyRetries as ex:
raise
else: # No exception
n_tries = 0
finally:
common_restore_state()
continue
解决方案 22:
该else:
块令人困惑且(几乎)无用。它也是for
andwhile
语句的一部分。
实际上,即使在if
-statement 上,也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
- 条件以使其明确。