网络与开发工具实战笔记
代理配置
约 9 分钟读完

pip 和 Python requests 怎么走 HTTP 与 SOCKS5 代理

pip 认 --proxy、PIP_PROXY、HTTPS_PROXY 和 pip.conf 里的 proxy;requests 在每次调用里传 proxies 字典,SOCKS5 要多装 PySocks。HTTP 代理时 https 那一项的值依然以 http:// 开头。

编辑部

Python 里要用代理,先分清是 pip 还是你写的脚本。pip 是命令行工具,通过 --proxy、环境变量或配置文件设置;脚本里的 requests 则在每次调用时传 proxies 字典。要走 SOCKS5,两边都得先装 PySocks。本文按 2026 年 11 月的状态写,代理地址全部是占位符。

pip 装包怎么走代理?

三种方式,按"临时程度"从高到低排列:命令行参数、环境变量、配置文件。pip 的 --proxy 接受 scheme://[user:password@]host:port 形式的地址。

# 一次性
python -m pip install --proxy http://user:password@proxy.example.com:8080 requests

# 当前终端
export HTTPS_PROXY=http://proxy.example.com:8080

# 写进用户配置文件
python -m pip config set global.proxy http://proxy.example.com:8080
python -m pip config list
python -m pip config unset global.proxy

建议养成写 python -m pip 的习惯。机器上有多个 Python 或虚拟环境时,这样能确保你配置和安装的是同一个解释器。想知道 pip 实际读了哪些配置文件,运行 python -m pip config debug。另外 pip 也认 PIP_PROXY 环境变量(pip 的每个选项都可以这样用 PIP_ 加选项名来设置)。

认证信息和特殊字符的写法见前面的 给 git 配代理,前端项目的对应配置见 npm、pnpm、yarn 的代理设置。

requests 的 proxies 字典怎么写?

键是"目标网站"的协议,值是"代理服务器"的地址。很多人疑惑为什么访问 HTTPS 网站时 https 对应的值还要写 http://:因为普通 HTTP 代理是通过 CONNECT 方法替客户端打通一条隧道,加密流量原样穿过,代理本身的地址依然是 http:// 开头。

import requests

proxy = "http://user:password@proxy.example.com:8080"
proxies = {"http": proxy, "https": proxy}

r = requests.get("https://api.ipify.org", proxies=proxies, timeout=10)
print(r.text)

别忘了 timeout,不传的话 requests 可能一直等下去。密码含 @、/ 等保留字符时,先用 urllib.parse.quote 编码:

from urllib.parse import quote

password = quote("p@ss/word", safe="")
proxy = "http://user:" + password + "@proxy.example.com:8080"

环境变量和代码里的 proxies,谁说了算?

requests 默认 trust_env=True,会读 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY、NO_PROXY,还可能读 .netrc。官方文档特别提醒:给 Session.proxies 赋的值可能被环境变量里的代理覆盖。想确保用的是你指定的代理,办法是每次请求都显式传 proxies=,或者干脆把 trust_env 设为 False 让它不看环境。

s = requests.Session()
s.trust_env = False
r = s.get("https://api.ipify.org", proxies=proxies, timeout=10)

这条规则经常解释"脚本明明写了代理,抓包却看到走的是另一个地址"这类怪事:通常是终端里残留了旧的环境变量。

SOCKS5 要装什么,socks5 和 socks5h 怎么选?

requests 通过 PySocks 支持 SOCKS,官方推荐的装法是带 extra 安装 requests[socks]。地址里用 socks5h:// 让代理端解析域名,本机 DNS 不参与;写 socks5:// 则是本机先解析、再把 IP 交给代理。

python -m pip install "requests[socks]"

proxy = "socks5h://user:password@proxy.example.com:1080"
proxies = {"http": proxy, "https": proxy}

pip 本身走 SOCKS 也需要 PySocks,而且必须装在运行 pip 的那个解释器里。如果看到 "Missing dependencies for SOCKS support",这是个先有鸡还是先有蛋的问题:先不用 SOCKS 代理(或临时用 HTTP 代理)执行 python -m pip install pysocks,装好再切换。要注意,这里讲的是 TCP 连接,HTTP 请求用不到 SOCKS5 的 UDP 功能。

报错信息怎么读?

requests 把网络故障包成自己的异常,pip 则直接打印底层信息。看清原文就能判断卡在哪一层:代理连接、认证、TLS,还是目标站本身。

报错所在层检查什么
ProxyError: Cannot connect to proxy连代理主机、端口、协议头;防火墙
407 Proxy Authentication Required认证用户名密码;密码是否编码、是否被重置
Missing dependencies for SOCKS support本地环境在同一个解释器里装 PySocks
SSLError: certificate verify failedTLS代理或网关在解密 HTTPS;提供它的根证书,不要关闭验证
ConnectTimeout / ReadTimeout网络路径或目标站慢用 curl 走同一代理对比

分不清是代码问题还是代理问题时,先拿 curl 做对照:同一个代理、同一个地址,curl 能通而 Python 不通,问题就在 Python 这一侧的配置。

怎么确认脚本真的走了代理?

最直接的办法是对比:让公共的"回显 IP"服务分别看一次直连和走代理时的来源地址,两个值不同就说明代理生效了。把检测函数建在一个关掉 trust_env 的 Session 上,可以避免残留的环境变量干扰结果;再分别捕获几类异常,出错时能立刻知道是哪一层的问题。

import requests
from requests.exceptions import ProxyError, ConnectTimeout, ReadTimeout

proxy = "http://user:password@proxy.example.com:8080"
proxies = {"http": proxy, "https": proxy}

def seen_ip(proxies=None):
    s = requests.Session()
    s.trust_env = False
    return s.get("https://api.ipify.org", proxies=proxies, timeout=10).text

print("直连:", seen_ip())
try:
    print("代理:", seen_ip(proxies))
except ProxyError as e:
    print("代理或认证有问题:", e)
except (ConnectTimeout, ReadTimeout) as e:
    print("超时:", e)

在终端里可以用 curl -x http://proxy.example.com:8080 https://api.ipify.org 做同样的检查。curl 和 Python 的结果不一致时,依次排查环境变量、trust_env,以及跑脚本的到底是哪个解释器(虚拟环境里的 pip 和系统的 pip 经常不是同一个)。

脚本里的密码怎么处理才不尴尬?

把代理地址写死在源码里,迟早会被提交进仓库。更稳妥的做法有两种:一是由运行环境注入 HTTPS_PROXY / HTTP_PROXY,脚本里不出现凭据,pip 和 requests 都会读到;二是使用支持来源 IP 白名单的代理,运行脚本的机器被放行后,地址里根本不需要密码。无论哪种,密码一旦被重置,凡是写死过它的地方都要更新。

安泊 VPN 能在哪里帮上忙

安泊 VPN 的代理 IP(HTTP/SOCKS5 proxy)独占一个 IP,HTTP 端口(含 HTTPS 隧道)和 SOCKS5 端口共用同一组用户名密码,上面的写法可以直接套用。不支持 SOCKS5 UDP,但 pip 和 requests 只用 TCP,不受影响。把机器加入来源 IP 白名单后,脚本里无需密码。用量计入流量套餐,用尽后代理关闭。详见代理 IP 页面。

参考资料

pip
python
requests
SOCKS5
代理配置

常见问题

为什么 pip 能走代理,我自己写的 requests 脚本却不走?
pip 读取了你终端里的 HTTPS_PROXY 等环境变量或 pip 配置,而脚本在另一个环境(比如计划任务、IDE、容器)里运行,没有这些变量。检查脚本运行环境里的 env,或者在代码里显式传 proxies 参数并设置 timeout。
requests 里 session.proxies 设了却被覆盖,怎么办?
官方文档明确说过,环境变量里的代理可能覆盖 Session.proxies。要么在每次 get、post 调用里显式传 proxies 参数,要么把 session.trust_env 设为 False 让它忽略环境变量。两种办法都不依赖运行环境里有什么变量。
SOCKS5 代理不支持 UDP,会影响 pip 和 requests 吗?
不会。pip 和 requests 发的都是基于 TCP 的 HTTP 请求。SOCKS5 UDP 只对依赖 UDP 的软件有意义,例如部分游戏或基于 QUIC 的客户端。如果你的场景涉及这类软件,选代理前要确认是否支持。
公司代理证书导致 certificate verify failed,可以直接关掉校验吗?
不建议。这类错误通常是代理在解密并重新签名 HTTPS 流量,把代理的根证书交给 pip(--cert 选项)或 requests(verify 参数指向证书文件)就能正常校验。关闭校验会让所有下载失去保护。
广告
  • 动态、住宅、家宽 3 类 IP
  • 不限设备数,一个账户多端共享
  • 智能分流与 TUN 模式
注册赠送流量

返回文章列表

返回文章列表

相关文章

代理配置

给 git 配代理:http.proxy、SSH 与克隆慢的排查

git 的 HTTPS 和 SSH 走两条独立的网络路径:前者读 http.proxy 或 https_proxy 环境变量,后者要在 ~/.ssh/config 里写 ProxyCommand。克隆慢先用 GIT_CURL_VERBOSE 看清实际连的是谁。

git
代理配置
SOCKS5