网络编程实践建议
约 1149 字大约 4 分钟
2026-05-10
网络代码要从“能跑”变成“可靠”,需要遵守一些实践原则。
- 一定要设置超时
- 合理重试
- 统一封装 API Client
- 复用连接
- 1默认套路:requests.get(url, params=..., timeout=5) + raise_for_status() + 分类捕获异常。
- 2项目变大就把请求收敛到 api_client.py:换 Token、加代理、换重试策略时不用满地图找代码。
- 3日志必带 url/method/status/error;但 Token/Cookie/密码必须脱敏(保留首 4 位足够定位)。
- 4永远不要 except Exception: pass —— 至少 logger.exception 或抛业务异常,吞错最难排查。
- 5区分清楚:网络错误(Timeout/ConnectionError)、HTTP 状态错(4xx/5xx)、解析错(ValueError)、业务错(接口返回 code != 0)。
网络代码要从“能跑”变成“可靠”,需要遵守一些实践原则。
一定要设置超时
requests.get(url, timeout=5)没有超时的请求可能永远卡住。
合理重试
只重试适合重试的错误,并设置最大次数和退避策略。不要盲目重试非幂等请求。
统一封装 API Client
不要在业务代码中到处散落 HTTP 请求。封装客户端可以统一 base URL、认证、超时、错误处理和日志。
复用连接
requests 使用 Session,httpx 使用 Client 或 AsyncClient。
session = requests.Session()连接复用可以减少 TCP/TLS 握手成本。
不要手动拼接 URL
使用 params 或 urllib.parse.urlencode()。
区分错误类型
至少区分:
- 网络错误
- 超时错误
- HTTP 状态码错误
- JSON 解析错误
- 业务错误
不同错误的处理方式不同。
大文件流式处理
不要一次性把大文件读入内存。requests 下载大文件时使用 stream=True。
日志要脱敏
记录请求日志时,不要打印 Token、Cookie、密码等敏感信息。
高并发要限流
无论线程池、asyncio 还是爬虫,都要限制并发数量。并发过高可能导致自己或对方服务不可用。
不要吞掉异常
反例:
try:
requests.get(url)
except Exception:
pass至少要记录日志,必要时抛出自定义异常。
给初学者的一套默认模板
如果你不知道怎么写一个比较稳的请求,可以先用这个模板:
import requests
def fetch_json(url, params=None):
try:
response = requests.get(url, params=params, timeout=5)
response.raise_for_status()
return response.json()
except requests.Timeout:
print('请求超时')
except requests.ConnectionError:
print('连接失败')
except requests.HTTPError as exc:
print(f'HTTP 错误:{exc}')
except ValueError:
print('响应不是 JSON')
return None
data = fetch_json('https://httpbin.org/get', params={'q': 'python'})
if data is not None:
print(data)这个模板不复杂,但包含了几个重要习惯:params、timeout、raise_for_status()、异常处理。
不要把网络请求散落到各处
项目稍微变大后,如果每个文件里都直接写请求,很快会变乱:
user.py requests.get(...)
order.py requests.post(...)
report.py requests.get(...)更好的做法是集中到一个模块里:
api_client.py 统一处理 base_url、headers、timeout、错误
user.py 调用 api_client.list_users()
order.py 调用 api_client.create_order()这样修改 Token、代理、重试、日志时,不需要到处找代码。
日志要能帮助排查
网络请求失败时,至少要能知道:
- 请求的 URL;
- 请求方法;
- 状态码;
- 错误类型;
- 简短响应内容;
- 本次请求的业务含义。
但不要打印完整 Token、Cookie、密码。
一个简单例子:
try:
response = requests.get(url, timeout=5)
response.raise_for_status()
except requests.RequestException as exc:
print(f'请求失败 url={url} error={exc}')
raise真实项目可以换成 logging 模块,而不是一直用 print。
什么时候该停下来
很多初学者遇到网络错误,会不断加重试、加 sleep、换 Header,最后代码越来越乱。其实有些情况应该停下来确认:
- 接口文档是否变了;
- 账号是否还有权限;
- Token 是否过期;
- 服务端是否正在故障;
- 是否触发了限流;
- 是否应该联系接口提供方。
工程上,能清楚地失败,比假装成功更重要。
总结
可靠网络代码的关键词是:超时、重试、限流、连接复用、统一封装、错误处理、安全脱敏。做到这些,代码会比简单调用 requests.get() 稳定得多。
- 初学者写网络请求时,默认使用 params、timeout、raise_for_status 和清晰异常处理。
- 项目变大后,把请求逻辑集中到 API Client 或独立模块里,不要散落到各处。
- 日志要帮助排查,但敏感信息必须脱敏;有些错误应该停下来确认,而不是无限重试。
版权所有
版权归属:Shuo Liu
