循环中如果出现错误,重复执行迭代

25

是否有类似于breakcontinue的命令可以重复最近的迭代?

例如,在抛出异常时。

for i in range(0,500):
    try:
        conn = getConnection(url+str(i))
        doSomething(conn)
    except:
        repeat

让我们进行一次迭代,其中i变量的值为6。在此迭代过程中出现了一些连接错误。我想重复这个迭代。

有没有一个命令可以做到这一点?

当然,我可以这样做:

i=0
while i!=500:
    try:
        conn = getConnection(url+str(i))
        doSomething(conn)
        i+=1
    except:
        pass

1
如果您的问题是如何在Python中实现此操作,那么Python没有内置的语法可以实现。但是,您可以在except子句中重试相同的函数。 - Greg
1
你可以使用生成器,yield每个成功的连接。 - Pierre Alex
7个回答

24

不,Python中没有“倒带”for循环的命令。

你可以在for循环内部使用一个while True:循环:

for i in range(500):
    while True:
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
        except Exception: # Replace Exception with something more specific.
            continue
        else:
            break

或者没有else::

for i in range(500):
    while True:
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
            break
        except Exception: # Replace Exception with something more specific.
            continue

但我个人认为你提出的解决方案更好,因为它避免了增加一层缩进。


1
裸露的 except 使得无法在没有 kill -9 的情况下停止该程序。 - m.wasowski
是的,我当时把重点放在循环上了,忽略了那个。已经修复了。 - user2555451
一切都很好,但这将涉及Python中迭代器实现方式的相当严重的更改。 - Veltzer Doron

4
for i in range(500):
    while True
        try:
            conn = getConnection(url+str(i))
            break
        except Exception: # still allows to quit with KeyboardInterrupt
            continue
    do_your_stuff()

这看起来有些危险,不过你应该至少在while块内启用一些日志记录。

如果你希望在更多的地方使用它,可以编写一个简单的装饰器:

def keep_trying(fn, *args, **kwargs):
    def inner(*args, **kwargs):
        while True:
            try:
                return fn(*args, **kwargs)
            except Exception:
                continue
    return inner

# later you can use it simple like this:
for i in range(500):
    conn = keep_trying(getConnection)(url+str(i))

2
您可以使用生成器:
def process_connections(n_connections, url, max_tries=50):
    i = 0
    try_count = 0
    while i < n_connections:
        try:
            conn = getConnection(url+str(i))
            yield conn
        except:
            try_count += 1
            if try_count > max_tries:
                raise Exception("Unable to connect after %s tries" % max_tries)
        else:
            i += 1 # increments only if no exception 

您执行操作:

for conn in process_connections(500, url):
    do_something(conn)

如果连接出现问题,是否可能出现无限循环? - Marichyasana

1
你可以使用嵌套的for循环来限制重试操作的次数。这基本上与@PierreAlex的生成器答案相同,但不需要额外的函数定义。
for i in range(500):
    for retry in range(10):
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
        except Exception: # Replace Exception with something more specific.
            time.sleep(1)
    else:
        print "iteration", i, "failed"

0

为什么不直接使用一个if语句呢?

n=6
i=0
while i!=500:
    failed = False;
    try:
        conn = getConnection(url+str(i))
        doSomething(conn)
        i+=1
    except:
        #handle error
        failed = True;

    #try again if n-th case failed first time
    if(i == n and failed):
        try:
            conn = getConnection(url+str(i))
            doSomething(conn)
        except:
            #handle error

0
这里有一个解决方案。您需要添加记录或警报系统,以便让您知道出现了卡顿问题。
state = "" #state of the loop

# If there is no error continue. If there is error, remain in loop
while True:
  if state != "error": 
    try:
      1/0 # command
      break # no error so break out of loop
    except:
      state = "error" #declare error so maintain loop
      continue
  elif state == "error": # maintain loop
    continue

0
这里有一种不同的方法,如果出现异常,它会返回带有参数的函数。
retries = 0
max_retries = 5

def x(a, b):
  global retries
  global max_retries
  print(retries)
  try:
    d = a / b
  except:
    retries += 1
    if retries >= max_retries:
      return {}
    else:
      return x(a, b)

a = 0
b = 0
y = x(a, b)
print(y)

0
1
2
3
4
{}

演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接