mur*_*d99 58 python error-handling
我在Python中有一段代码似乎在概率上导致错误,因为它正在访问服务器,有时该服务器有500内部服务器错误.我想继续尝试,直到我没有得到错误.我的解决方案是:
while True:
try:
#code with possible error
except:
continue
else:
#the rest of the code
break
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎是个黑客.是否有更多的Pythonic方法来做到这一点?
小智 57
它不会变得更清洁.这不是一件非常干净的事情.充其量(无论如何,这将是更可读的,因为它的条件break是在那里while),你可以创建一个变量result = None并循环它is None.你也应该调整变量,你可以continue用语义替换也许正确pass(你不关心是否发生错误,你只是想忽略它)并删除break- 这也得到了其余的代码,只执行一次, 跳出循环.另请注意,由于文档中给出except:的原因,裸条款是邪恶的.
包含以上所有内容的示例:
result = None
while result is None:
try:
# connect
result = get_data(...)
except:
pass
# other code that uses result but is not involved in getting it
Run Code Online (Sandbox Code Playgroud)
mou*_*uad 24
也许是这样的:
connected = False
while not connected:
try:
try_connect()
connected = True
except ...:
pass
Run Code Online (Sandbox Code Playgroud)
rad*_*tek 19
这是一次尝试4次后硬盘失败,并在两次尝试之间等待2秒.根据您的需要进行更改以获得您想要的内容:
from time import sleep
for x in range(0, 4): # try 4 times
try:
# msg.send()
# put your logic here
str_error = None
except Exception as str_error:
pass
if str_error:
sleep(2) # wait for 2 seconds before trying to fetch the data again
else:
break
Run Code Online (Sandbox Code Playgroud)
这是退避的示例:
from time import sleep
sleep_time = 2
num_retries = 4
for x in range(0, num_retries):
try:
# put your logic here
str_error = None
except Exception as str_error:
pass
if str_error:
sleep(sleep_time) # wait before trying to fetch the data again
sleep_time *= 2 # Implement your backoff algorithm here i.e. exponential backoff
else:
break
Run Code Online (Sandbox Code Playgroud)
由于错误而重试时,您应该始终:
在解决这些问题的同时解决这个问题的一个简单的通用方法是使用退避库。一个基本的例子:
import backoff
@backoff.on_exception(
backoff.expo,
MyException,
max_tries=5
)
def make_request(self, data):
# do the request
Run Code Online (Sandbox Code Playgroud)
此代码使用实现重试逻辑的装饰器包装 make_request。每当MyException发生特定错误时,我们都会重试,重试次数限制为 5 次。 在这种情况下,指数退避是一个好主意,可以帮助最大程度地减少重试给远程服务器带来的额外负担。
这些itertools.iter_except食谱封装了“重复调用函数直到引发异常”的想法。它类似于接受的答案,但配方提供了一个迭代器。
从食谱:
def iter_except(func, exception, first=None):
""" Call a function repeatedly until an exception is raised."""
try:
if first is not None:
yield first() # For database APIs needing an initial cast to db.first()
while True:
yield func()
except exception:
pass
Run Code Online (Sandbox Code Playgroud)
你当然可以直接实现后面的代码。为方便起见,我使用了一个单独的库,more_itertools为我们实现了这个秘诀(可选)。
代码
import more_itertools as mit
list(mit.iter_except([0, 1, 2].pop, IndexError))
# [2, 1, 0]
Run Code Online (Sandbox Code Playgroud)
细节
在这里pop,为列表对象的每次迭代调用方法(或给定函数),直到IndexError引发an 。
对于您的情况,给定一些connect_function和预期的错误,您可以创建一个迭代器,重复调用该函数直到引发异常,例如
mit.iter_except(connect_function, ConnectionError)
Run Code Online (Sandbox Code Playgroud)
此时,通过循环或调用next().