在python中引发异常后重复某些内容的最优雅方法是什么?
我有类似的东西[伪代码作为例子]:
try:
do_some_database_stuff()
except DatabaseTimeoutException:
reconnect_to_database()
do_some_database_stuff() # just do it again
但是想象一下,如果我没有一个很好的功能,而是很多代码。重复的代码不是很好。
所以我认为这稍微好一些:
while True:
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
reconnect_to_database()
如果异常确实解决了问题,那就足够了。如果不是,我需要一个计数器来防止无限循环:
i = 0
while i < 5:
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
reconnect_to_database()
i += 1
但是我不知道它是否有效,所以它也是:
while i <= 5:
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
if i != 5:
reconnect_to_database()
else:
raise DatabaseTimeoutException
i += 1
正如你所看到的,它开始变得非常混乱。
表达这种逻辑的最优雅方式是什么?
答案 0 :(得分:6)
您可以使用&#34; for-else&#34;循环:
for ii in range(5):
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
reconnect_to_database()
else:
raise DatabaseTimeoutException
或者,没有:
for ii in range(5):
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
if ii == 4:
raise
reconnect_to_database()
答案 1 :(得分:1)
我个人不是for-else构造的粉丝。我不认为它是直观的。我第一次阅读它时,我认为它意味着“为循环(...)做,如果迭代是空的那么......”。
您应该将代码放在函数中。如果do_some_database_stuff()
成功完成,那么您可以使用return语句从函数中提前返回。
例如
def try_to_do_some_database_stuff():
for i in range(num_times):
try:
return do_some_database_stuff()
except DatabaseTimeoutException:
reconnect_to_database()
raise DatabaseTimeoutException
如果您发现自己使用此构造很多,那么您可以使它更通用。
def try_to_do(func, catch, times=2, on_exception=None):
for i in range(times):
try:
return func()
except catch:
if on_exception:
on_exception()
raise catch
try_to_do(do_some_database_stuff, catch=DatabaseTimeoutException, times=5,
on_exception=reconnect_to_database)
如果需要将参数传递给函数,可以使用functools.partial
。