在python中,如何在出现异常时重复某些内容?

在python中,如何在出现异常时重复某些内容?,python,python-2.7,Python,Python 2.7,在python中导致异常后,最优雅的重复方式是什么 我有这样的东西[以伪代码为例]: try: do_some_database_stuff() except DatabaseTimeoutException: reconnect_to_database() do_some_database_stuff() # just do it again 但是想象一下,如果我没有一个很好的函数,而是有很多代码。重复的代码不是很好 所以我觉得这稍微好一点: while True: try:

在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
i=0
当我<5时:
尝试:
做一些数据库的工作
打破
除DatabaseTimeoutException外:
将_重新连接到_数据库()
i+=1
但我真的不知道它是否有效,所以它也是:

while i <= 5:
  try:
    do_some_database_stuff()
    break
  except DatabaseTimeoutException:
    if i != 5:
     reconnect_to_database()
    else:
      raise DatabaseTimeoutException
    i += 1
当i时,您可以使用“”循环:

或者,没有:

for ii in range(5):
    try:
        do_some_database_stuff()
        break
    except DatabaseTimeoutException:
        if ii == 4:
            raise
        reconnect_to_database()

我个人不喜欢for else结构。我认为这不是直觉。第一次读它的时候,我想它的意思是“DoforLoop(…),如果iterable是空的,那么…”

您应该将代码放在函数中。如果
do\u some\u database\u stuff()
成功完成,则可以使用return语句提前从函数返回

例如

如果你发现自己经常使用这个结构,那么你可以使它更通用

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

该问题的最上面的答案是“但每当看到[a for else]构造时,更好的替代方法是…”。我同意。最好将代码块包装在一个函数中,并使用return而不是break。@Dunes:这就是为什么我提供了一个替代方法,供那些认为for-else有点过分的人使用。我个人对此持怀疑态度,这当然是一个品味问题。
for else
版本并不等效,因为它将在5次故障时运行
重新连接到\u数据库
5次,而不是4次。这将在5次故障时运行
重新连接到\u数据库
5次,这似乎有点毫无意义。它复制了问题中循环的行为。if语句中的额外
i+1
足以更改行为,使其不响应最后一个异常。
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)