Python 用于在发生异常时重新尝试代码块的设计模式

Python 用于在发生异常时重新尝试代码块的设计模式,python,design-patterns,Python,Design Patterns,我正试图找到一种设计模式——我确信有一种模式存在,这个问题很常见 在我的应用程序中,如果用户失去Internet连接,我希望能够暂停应用程序,允许用户检查连接并重试。当连接成功时,应用程序将离开其停止的位置 我曾经这样尝试过: while True: try: for url in urls: downloadPage(url) except ConnectionException: raw_input('Connection los

我正试图找到一种设计模式——我确信有一种模式存在,这个问题很常见

在我的应用程序中,如果用户失去Internet连接,我希望能够暂停应用程序,允许用户检查连接并重试。当连接成功时,应用程序将离开其停止的位置

我曾经这样尝试过:

while True:
   try:
       for url in urls:
           downloadPage(url)
   except ConnectionException:
       raw_input('Connection lost. Press enter to try again')
       continue
但这不起作用,因为如果在for循环中引发异常,它将捕获它,但当它继续时,它将从
url
列表的开头重新启动

我确实需要在应用程序开始运行之前和每次请求期间检查连接错误。这样我就可以暂停了。但是我不想在我的代码中乱扔
try/catch


有这样的模式吗?

您可以在for循环中移动try

for url in urls:
    while True:
        try:
            downloadPage(url)
        except ConnectionException:
            raw_input('Connection lost. Press enter to try again')
为什么不是这个

while True:
   for url in urls:
       success = False
       while (not success):
           try:
               downloadPage(url)
               success = True
           except ConnectionException:
               raw_input('Connection lost. Press enter to try again')

这将尝试连接最多3次,然后删除当前url并转到下一个url。所以,如果无法建立连接,您不会陷入困境,但仍然有机会访问每个url

for url in urls:
    retries = 3
    while True:
        try:
            downloadPage(url)
        except ConnectionException:
            retries -= 1
            if retries == 0:
                print "Connection can't be established for url: {0}".format(url)
                break            
            raw_input('Connection lost. Press enter to try again')
您可以在一个地方“抽象”掉这些缺点(不必像您所说的那样“用try/catch块乱扔我所有的代码”——这就是上下文管理器的作用!一个简单的例子…:

import contextlib

@contextlib.contextmanager
def retry_forever(exception=ConnectionException, message='Connection lost. Press enter to try again'):
    while True:
        try: yield
        except exception:
            raw_input(message)
        else: break
现在,你可以使用

for url in urls:
    with retry_forever():
        downloadPage(url)
更好的变体(最大重试次数,&c)也可以优雅地重构为这种非常有用的形式。

您可以使用


只要写一段代码,在失败时不断重复,直到达到最大重试次数为止。

如果连接从未出现,这将永远循环。但是如果我创建一个新函数,在Internet上执行类似于上面的请求,那将意味着我必须重复相同的代码。@LOLKAT我不知道你在问什么。您总是可以将这段代码放入函数中,并为每次调用传递它
url
。这样你就不会重复代码了。啊,说得好。通过函数传递所有请求。问题解决了。谢谢。@PadraicCunningham这就是OP想要的。设计模式可能包括使用continuations,但是,对于大多数用例,正确的检查点就足够了(写下在循环中进行迭代时所取得的进展,在连接丢失错误上严重失败,然后在开始时阅读检查点日志以确定在何处继续处理)。OP只想继续重试,直到成功。这没什么错。顺便说一句,Python中没有“catch”。您要查找的关键字是“除了“@selbie good catch,no pun,我今天一直在交替使用C#和Python。已修复。我想你的意思是,
print”无法为url:{0}建立连接。format(url)
@PadraicCunningham:当然,是一个拼写错误。会修复的。谢谢!你也可以使用
进行范围内的尝试(3):
并且不再需要while循环、if、break等…@padraiccnningham:当然可以:)