Python中使用try-except处理网络请求,有没有更好的写法?

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

有没有更优雅的写法?

样例代码:

import requests

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

print response.status_code


Python中使用try-except处理网络请求,有没有更好的写法?

12 回复

对面服务器挂了, 你这个就是死循环了, 好一点的办法是捕捉异常之后把失败的 url 放到失败队列中, 找个机会重试


对于网络请求的异常处理,try-except是标准做法,但可以结合requests库的特性写得更好。下面是个改进示例:

import requests
from requests.exceptions import RequestException, Timeout, HTTPError
import logging

def make_request(url, timeout=5):
    try:
        response = requests.get(url, timeout=timeout)
        response.raise_for_status()  # 自动检查HTTP状态码
        return response.json()
        
    except Timeout:
        logging.warning(f"请求超时: {url}")
        return None
        
    except HTTPError as e:
        logging.error(f"HTTP错误 {e.response.status_code}: {url}")
        return None
        
    except RequestException as e:
        logging.error(f"请求失败: {e}")
        return None
        
    except ValueError:  # JSON解析失败
        logging.error(f"响应不是有效的JSON: {url}")
        return None

# 使用示例
result = make_request("https://api.example.com/data")
if result:
    print("成功获取数据")

关键改进点:

  1. 使用response.raise_for_status()自动检查HTTP状态码,避免手动检查
  2. 捕获具体的异常类型(TimeoutHTTPError等)而不是笼统的Exception
  3. 添加适当的日志记录
  4. 包含JSON解析异常处理
  5. 设置合理的超时时间

如果使用第三方库,可以考虑aiohttp(异步)或httpx(同步/异步都支持),它们提供更现代的API。

总结:细化异常类型,结合raise_for_status()和适当日志。

这当然是个好的办法,但在这里只想探索下这段代码有没有好的写法

装饰器加设置重试

python<br>def request_retry(times):<br> def decorator(func):<br> def wrapper(*args, **kwargs):<br> while times &gt; 0:<br> try:<br> return func(*args, **kwargs)<br> # 各种异常捕获<br> except RequestException as e:<br> times -= 1<br> else:<br> raise HTTPRequestFailedException() # 自定义的异常<br> return wrapper<br> return decorator<br>

没有, 网络异常是必然的, 可预见的, 必须加异常处理, 至于怎么处理看业务需求

可以的,装饰器写法 get 了

回复不支持 markdown 真是蛋疼,缩进都没了,上面的 else 是 while…else,不是 try…except…else。

timeout 设置一波啊,你用 try 不就想在制定时间得到响应吗,不然用 try 干嘛,要是请求失败要等好久的,所以肯定要设置超时啊

工程里 timeout 设置了,最大请求次数也设置了,跑起来效率和准确度还行,只是觉得这样一坨代码写的有点丑(笑哭

了然~ 代码看懂了

可以试下递归。

贴一串以前的,用 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)

回到顶部