第一选择
有一个需要处理的值列表 - 如果一个失败,重新开始迭代,但在一个较小的列表上。
vals = [10, 11, 12, 13, 14]
# processing 12 will fail the first time
first_try_12 = True
to_do = vals
while to_do:
print("starting attempts...")
for i, val in enumerate(to_do):
try:
if val == 12 and first_try_12:
first_try_12 = False
raise RuntimeError("blah")
print("Did", val)
except RuntimeError:
print("barfed on ", val)
to_do = to_do[i:] # <== this is allowed - see below
break
else:
to_do = [] # finished all iterations, so there is no more to do
给予:
starting attempts...
Did 10
Did 11
barfed on 12
starting attempts...
Did 12
Did 13
Did 14
顺便说一句,关于在 except 块内对to_do 的赋值,不必担心它正在修改我们正在迭代的列表,因为:(1)它没有修改列表(对象),它正在重新分配一个名称,并且 (2) 无论如何我们都将退出循环。
第二个选项
只遍历列表一次,但在 for 循环内,重试每个项目直到成功。
vals = [10, 11, 12, 13, 14]
# processing 12 will fail the first time
first_try_12 = True
to_do = vals
print("starting attempts...")
for i, val in enumerate(to_do):
succeeded = False
while not succeeded:
try:
if val == 12 and first_try_12:
first_try_12 = False
raise RuntimeError("blah")
print("Did", val)
succeeded = True
except RuntimeError:
print("barfed on ", val)
给予:
starting attempts...
Did 10
Did 11
barfed on 12
Did 12
Did 13
Did 14
这与上面的输出相同,只是“开始尝试...”只打印一次。因此,哪个选项更可取可能取决于任何初始化是否只需要进行一次,还是在失败后继续时重复。