Python:遇到超时时如何重试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18839998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:02:13  来源:igfitidea点击:

Python: How to try again when experiencing a timeout

pythontry-catch

提问by ark

I have a python program that connects to a server to send it some commands but occisonally I get this error

我有一个连接到服务器的 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

In previous situtations like this I would use something like this

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

try:
            do something
        except KeyError:
            do something else

Could I do the same thing in this same situtation ie

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

try:
                do something
            except TimeoutError:
               do something again

and if so what would I do after the except TimeoutError? would I just do the same command again?

如果是这样,除了 TimeoutError 之后我会做什么?我会再次执行相同的命令吗?

采纳答案by abarnert

Could I do the same thing in this same situtation

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

Yes! You can use try/exceptfor anyexception, and TimeoutErroris nothing special.

是的!您可以将try/except用于任何异常,并TimeoutError没有什么特别之处。

and if so what would I do after the except TimeoutError? would I just do the same command again?

如果是这样,除了 TimeoutError 之后我会做什么?我会再次执行相同的命令吗?

If you only want to retry once, and let a second timeout count as a real error, yes:

如果你只想重试一次,并让第二次超时算作真正的错误,是的:

try:
    do something
except TimeoutError:
    do something

(If "do something" is more than a simple statement, you probably want to factor out the code so you don't repeat yourself.)

(如果“做某事”不仅仅是一个简单的陈述,您可能希望将代码分解出来,这样您就不会重复自己了。)

However, if you want to retry multiple times, you probably want a loop:

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

for _ in range(max_retries):
    try:
        do something
        break
    except TimeoutError:
        pass

You may want to add an elseclause to the forto distinguish the two cases (succeeded, and did a break, vs. never succeeded and just ran out of tries).

您可能想在 中添加一个else子句来for区分这两种情况(成功,并且做了一个break,而从未成功,只是尝试用完了)。



Since the idea here is usually to deal with possibly-transient errors, there are additional things you might want to add, such as:

由于这里的想法通常是处理可能的暂时性错误,因此您可能需要添加其他内容,例如:

  • Re-raising the error, or raising a different one, after max_retries.
  • Logging at progressively higher levels (e.g., a debug message for a single failure, but a warning for `max_retries).
  • Retrying with exponential backoff (wait 1 second, then 2, 4, 8, …).
  • Pushing the URL to the end of the work queue instead of retrying immediately. You can use (URL, retry_count)pairs if you also want max_retrieslogic, (URL, timestamp)pairs if you also want exponential backoff, or both if you want both. (Of course this only works if you don't care about the order of responses, or can reorder them at the end.)
  • Different rules for different exceptions (e.g., 500, 502, 503, and 504 errors can all be caused by overload on a server or proxy, but the best retry logic may be different—and the best heuristics for 2018 may be different from 2010 or 2025).
  • max_retries.
  • 在逐渐更高的级别上记录(例如,单个失败的调试消息,但`max_retries 的警告)。
  • 使用指数退避重试(等待 1 秒,然后是 2、4、8……)。
  • 将 URL 推送到工作队列的末尾而不是立即重试。(URL, retry_count)如果您还需要max_retries逻辑,(URL, timestamp)则可以使用对,如果您还需要指数退避,则可以使用对,或者如果两者都需要,则可以使用两者。(当然,这仅在您不关心响应顺序或可以在最后重新排序时才有效。)
  • 针对不同异常的不同规则(例如,500、502、503 和 504 错误都可能由服务器或代理过载引起,但最佳重试逻辑可能不同——2018 年的最佳启发式可能与 2010 年不同或2025)。

For complicated combinations, a retry decorator, like the one linkedin jterrace's helpful answer, is a great way to wrap up the behavior.

对于复杂的组合,重试装饰,就像一个挂jterrace的有用的答案,是的收官之行为的好方法。

回答by jterrace

You can catch the TimeoutError like you mentioned:

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

import socket
import sys
try:
  dosomething()
except socket.TimeoutError:
  print >> sys.stderr, 'Retrying after TimeoutError'
  dosomething()

You could also use the retry decorator patternon a function:

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

@retry(socket.TimeoutError)
def dosomething():
    # code that causes a TimeoutError
    ...

回答by HennyH

def f():
    pass #insert code here

To repeat once after the error:

在错误后重复一次:

try:
    f()
except TimeoutError:
    f()

Or to loop until success:

或者循环直到成功:

while True:
    try:
        f()
        break
    except TimeoutError:
        pass

Or with a limited number:

或数量有限:

attempts = 3
while attempts:
    try:
        f()
        break
    except TimeoutError:
        attempts -= 1

回答by Cris

Please run each example, they are ready!

请运行每个示例,它们已准备就绪!

Example 1

示例 1

import sys

try:
    incorrect.syntaxThatIJustMadeUP()
except:
    print((sys.exc_info()[0])) #Now you know what to except and CATCH
else:
    print("You will never see this message")

Example 2

示例 2

import sys

try:
    incorrect.syntaxThatIJustMadeUP()
except NameError:
    print("There is a problem with your SYNTAX Dude!")
except:
    print((sys.exc_info()[0])) #Incase another uncontrollable network problem occurs, User rages-Snaps IJ45
else:
    print("You will never see this message unless TRY suceeds")
    print("Why not put this try in a loop")