使用 try-except 包含网络请求语句,有没有更好的写法?

2018-05-04 15:02:24 +08:00
 windcode

如题,想保证网络请求一定能获得返回的结果,目前常用写法见下。如果请求语句没报错,就跳出循环,否则反复发送网络请求,直到成功。

有没有更优雅的写法?

样例代码:

import requests

while True:
    try:
        response = requests.get('http://www.xxxxxxxxx.com')
        break
    except Exception,e:
        print str(e)

print response.status_code
2792 次点击
所在节点    Python
11 条回复
lihongjie0209
2018-05-04 15:04:53 +08:00
对面服务器挂了, 你这个就是死循环了, 好一点的办法是捕捉异常之后把失败的 url 放到失败队列中, 找个机会重试
windcode
2018-05-04 15:11:35 +08:00
@lihongjie0209 这当然是个好的办法,但在这里只想探索下这段代码有没有好的写法
glacer
2018-05-04 15:19:33 +08:00
装饰器加设置重试

```python
def request_retry(times):
def decorator(func):
def wrapper(*args, **kwargs):
while times > 0:
try:
return func(*args, **kwargs)
# 各种异常捕获
except RequestException as e:
times -= 1
else:
raise HTTPRequestFailedException() # 自定义的异常
return wrapper
return decorator
```
lihongjie0209
2018-05-04 15:22:20 +08:00
@windcode 没有, 网络异常是必然的, 可预见的, 必须加异常处理, 至于怎么处理看业务需求
windcode
2018-05-04 15:23:12 +08:00
@glacer 可以的,装饰器写法 get 了
glacer
2018-05-04 15:28:26 +08:00
@windcode 回复不支持 markdown 真是蛋疼,缩进都没了,上面的 else 是 while...else,不是 try...except...else。
Hopetree
2018-05-04 15:40:00 +08:00
timeout 设置一波啊,你用 try 不就想在制定时间得到响应吗,不然用 try 干嘛,要是请求失败要等好久的,所以肯定要设置超时啊
windcode
2018-05-04 15:42:23 +08:00
@Hopetree 工程里 timeout 设置了,最大请求次数也设置了,跑起来效率和准确度还行,只是觉得这样一坨代码写的有点丑(笑哭
windcode
2018-05-04 15:42:49 +08:00
@glacer 了然~ 代码看懂了
hcymk2
2018-05-04 15:51:08 +08:00
可以试下递归。
zhaoshengzhi
2018-05-04 16:26:19 +08:00
贴一串以前的,用 auto_retry 自动重试,用 time_limit 设置时间限制,也可以组合同时使用


import traceback
import json
import subprocess

import eventlet

eventlet.monkey_patch()

RETRY_COUNT = 10

TIMEOUT = 10


def time_limit(func, *args, **kwargs):
trace = None
for _ in range(RETRY_COUNT):
try:
with eventlet.Timeout(TIMEOUT):
return func(*args, **kwargs)
except eventlet.timeout.Timeout, e:
trace = format_traceback()
except:
trace = format_traceback()

ignore_exception = kwargs.get('ignore_exception')
if not ignore_exception:
raise Exception(
"max retry count=%d, func=%s, argv=%s, trace=%s" % (RETRY_COUNT, func.__name__, (args, kwargs), trace))


def auto_retry(func, *args, **kwargs):
trace = None
for _ in range(RETRY_COUNT):
try:
return func(*args, **kwargs)
except:
trace = format_traceback()

ignore_exception = kwargs.get('ignore_exception')
if not ignore_exception:
raise Exception(
"max retry count=%d, func=%s, argv=%s, trace=%s" % (RETRY_COUNT, func.__name__, (args, kwargs), trace))


def format_traceback():
trace = traceback.format_exc()
return json.dumps(trace, ensure_ascii=False)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/452109

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX