[英]How to repeat something upon exception in python?
What is the most elegant way to repeat something after it caused an exception in python? 在python中导致异常之后重复某些事情的最优雅方法是什么?
I have something like this [pseudo code as an example]: 我有这样的东西[伪代码作为例子]:
try:
do_some_database_stuff()
except DatabaseTimeoutException:
reconnect_to_database()
do_some_database_stuff() # just do it again
But imagine if I don't have a nice function but a lot of code instead. 但想象一下,如果我没有一个很好的功能,而是很多代码。 Duplicate code is not very nice.
重复的代码不是很好。
So I think this is slightly better: 所以我认为这稍微好一些:
while True:
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
reconnect_to_database()
That's good enough if the exception really fixes the problem. 如果异常确实解决了问题,那就足够了。 If not I need a counter to prevent an indefinite loop:
如果不是,我需要一个计数器来防止无限循环:
i = 0
while i < 5:
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
reconnect_to_database()
i += 1
But then I don't really know if it worked so it's also: 但后来我真的不知道它是否有效,所以它也是:
while i <= 5:
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
if i != 5:
reconnect_to_database()
else:
raise DatabaseTimeoutException
i += 1
As you can see it starts to get very messy. 你可以看到它开始变得非常混乱。
What is the most elegant way of expressing this logic? 表达这种逻辑的最优雅方式是什么?
You can use a " for-else " loop: 您可以使用“ for-else ”循环:
for ii in range(5):
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
reconnect_to_database()
else:
raise DatabaseTimeoutException
Or, without: 或者,没有:
for ii in range(5):
try:
do_some_database_stuff()
break
except DatabaseTimeoutException:
if ii == 4:
raise
reconnect_to_database()
I'm personally not a fan of the for-else construct. 我个人不是for-else构造的粉丝。 I don't think it's intutitive.
我不认为它是直观的。 First time I read it I thought it meant "do for loop (...), if iterable was empty then ...".
我第一次阅读它时,我认为这意味着“为循环(...)做,如果迭代是空的那么......”。
You should place your code inside a function. 您应该将代码放在函数中。 If
do_some_database_stuff()
completes successfully then you can use the return statement to return early from the function. 如果
do_some_database_stuff()
成功完成,那么您可以使用return语句从函数中提前返回。
eg. 例如。
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
If you find yourself using this construct quite a lot then you can make it more generic. 如果你发现自己使用这个构造很多,那么你可以使它更通用。
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)
You can use functools.partial
if you need to pass arguments to your functions. 如果需要将参数传递给函数,可以使用
functools.partial
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.