一个可控的 HTTP 代理示例

import os
import requests

proxy_url = os.environ["HTTPS_PROXY_URL"]
proxies = {"http": proxy_url, "https": proxy_url}

try:
    response = requests.get(
        "https://example.com/health",
        proxies=proxies,
        timeout=(5, 15),
    )
    response.raise_for_status()
except requests.exceptions.Timeout:
    print("request timed out")
except requests.exceptions.ProxyError:
    print("proxy connection failed")
except requests.exceptions.RequestException as exc:
    print(type(exc).__name__)

timeout=(5, 15) 分别表示连接阶段和读取阶段的等待设置。Requests 官方文档提醒:未显式设置 timeout 时,请求可能长期等待。

环境变量与显式配置

Requests 会读取 http_proxyhttps_proxyall_proxyno_proxy 等环境配置。为了让任务行为可复现,生产代码通常应明确决定是否继承环境代理,并在运行记录中注明。

包含用户名密码的代理 URL 属于敏感信息。官方文档也提醒,把凭据保存在环境变量或版本控制文件中存在风险;实际系统应使用受控的密钥管理机制并限制读取权限。

SOCKS 支持与 DNS

Requests 的 SOCKS 支持是可选功能,需要安装对应依赖。使用 socks5:// 时通常由客户端解析域名,使用 socks5h:// 时交给代理端解析。不要在不理解 DNS 边界时直接切换。

proxies = {
    "http": "socks5h://proxy.example:1080",
    "https": "socks5h://proxy.example:1080",
}

重试必须有限制

连接超时、临时 5xx 或限流可能适合有限重试,但认证失败、参数错误和权限拒绝通常不应盲目重试。只对可安全重放的操作使用退避,并设置最大次数、总时限和随机抖动。

日志中记录异常类别、耗时和匿名化请求标识即可,不应记录完整代理 URL、Proxy-Authorization、Cookie 或响应中的敏感数据。

上线前检查

  1. 锁定 Requests 与依赖版本并查看安全更新。
  2. 明确代理协议和 DNS 解析位置。
  3. 设置连接/读取超时及总体任务截止时间。
  4. 为直连、代理失败、认证失败和目标失败分别测试。
  5. 保持 TLS 验证开启,使用可信 CA 配置解决证书问题。

常见问题

Requests 的 timeout 是整个下载总时间吗?

不是简单的总时限。官方说明它主要控制连接或底层套接字在相应阶段的等待;业务还应设置总体任务截止时间。

为什么设置 session.proxies 后仍被环境变量覆盖?

Requests 官方文档说明环境代理可能覆盖 Session 设置。需要可重复行为时,应在每个请求中显式传入 proxies。

出现证书错误时可以 verify=False 吗?

不建议。应确认代理是否进行 TLS 检查,并配置受信任的 CA;关闭验证会失去服务器身份校验。

继续阅读

主要参考资料

资料最后复核:2026-09-05。外部文档可能更新,操作前请核对来源页面当前版本。