Python:如何在遇到超时时再试一次

ark*_*ark 2 python try-catch

我有一个连接到服务器的python程序,它发送一些命令但是我发现这个错误

TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Run Code Online (Sandbox Code Playgroud)

在以前的这种情况中,我会使用这样的东西

try:
            do something
        except KeyError:
            do something else
Run Code Online (Sandbox Code Playgroud)

我可以在同样的情况下做同样的事情,即

try:
                do something
            except TimeoutError:
               do something again
Run Code Online (Sandbox Code Playgroud)

如果是这样,除了TimeoutError之外我该怎么做?我会再次做同样的命令吗?

aba*_*ert 14

我是否可以在同样的情况下做同样的事情

是! 您可以使用try/ except进行任何异常,并TimeoutError没有什么特别之处.

如果是这样,除了TimeoutError之外我该怎么做?我会再次做同样的命令吗?

如果您只想重试一次,并将第二次超时计为真正的错误,则:是:

try:
    do something
except TimeoutError:
    do something
Run Code Online (Sandbox Code Playgroud)

(如果"做某事"不仅仅是一个简单的陈述,你可能想要分解代码,这样你就不会重复了.)

但是,如果要重试多次,可能需要循环:

for _ in range(max_retries):
    try:
        do something
        break
    except TimeoutError:
        pass
Run Code Online (Sandbox Code Playgroud)

您可能希望在其中添加一个else子句来for区分这两种情况(成功,执行了一次break,从未成功,只是用完了尝试).


由于这里的想法通常是为了处理可能出现的瞬态错误,因此您可能还需要添加其他内容,例如:

  • 之后重新提出错误或提出另一个错误max_retries.
  • 以逐渐更高的级别记录(例如,针对单个故障的调试消息,但是对于"max_retries"的警告).
  • 以指数退避重试(等待1秒,然后是2,4,8,......).
  • 将URL推送到工作队列的末尾,而不是立即重试.(URL, retry_count)如果您还需要max_retries逻辑,(URL, timestamp)则可以使用对,如果还需要指数退避,则可以使用对,如果需要,则可以使用两者.(当然,这只有在您不关心响应顺序时才有效,或者可以在最后重新排序.)
  • 不同异常的不同规则(例如,500,502,503和504错误都可能由服务器或代理上的过载引起,但最佳重试逻辑可能不同 - 2018年的最佳启发式可能与2010年或2025).

对于复杂的组合,重试装饰器(如在jterrace的有用答案中链接的装饰器)是一种很好的方式来结束行为.


jte*_*ace 6

您可以像上面提到的那样捕获TimeoutError:

import socket
import sys
try:
  dosomething()
except socket.TimeoutError:
  print >> sys.stderr, 'Retrying after TimeoutError'
  dosomething()
Run Code Online (Sandbox Code Playgroud)

您还可以在函数上使用重试装饰器模式:

@retry(socket.TimeoutError)
def dosomething():
    # code that causes a TimeoutError
    ...
Run Code Online (Sandbox Code Playgroud)