Skip to content

Drop requests dep and handle PEP 668 environments#1

Open
solfx wants to merge 1 commit intostormzhang:mainfrom
solfx:fix/pep668-drop-requests
Open

Drop requests dep and handle PEP 668 environments#1
solfx wants to merge 1 commit intostormzhang:mainfrom
solfx:fix/pep668-drop-requests

Conversation

@solfx
Copy link
Copy Markdown

@solfx solfx commented Apr 19, 2026

Summary

  • 用标准库 urllib.request 替换 requests,脚本在 Linux / macOS 上零第三方依赖即可运行,规避 Homebrew Python 3.11+ / 新版 Debian/Ubuntu 的 PEP 668 "externally-managed-environment" 报错。
  • Windows-only 的 colorama / tzdata 自动安装改为多策略(普通 → --user--break-system-packages --user),装不上时静默降级而非直接退出。

实际遇到的问题

在 macOS + Homebrew Python 3.14 的环境下直接运行 python ip_check.py,脚本检测到缺少 requests,提示自动安装并得到用户确认,但 pip install 被 PEP 668 拦截:

缺少依赖包: requests
是否自动安装?[Y/n] Y
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try brew install xyz...
    If you wish to install a Python library that isn't in Homebrew,
    use a virtual environment:
        python3 -m venv path/to/venv
        source path/to/venv/bin/activate
        python3 -m pip install xyz
    ...
    You may restore the old behavior of pip by passing
    the '--break-system-packages' flag...

脚本随后走到 ensurepip --upgrade 兜底分支,同样被拦截(引导出的 pip 依然受同一限制)并抛出 CalledProcessError,最终打印"无法自动安装 pip"后退出。用户拿到一个能跑的脚本,却在第一步就卡住。

受影响的环境不是个例,而是当前主流的"干净系统 Python":

  • Homebrew Python 3.11 / 3.12 / 3.13 / 3.14
  • Debian 12+、Ubuntu 23.04+、Fedora 38+ 等默认启用 PEP 668 的发行版
  • 详见 PEP 668

为什么这么改

考虑过的几种方案,按"用户侧摩擦从高到低"排列:

  1. 让用户手动 venv / pipx:能解决问题,但每次换机器都要记住激活流程,对非开发者用户门槛高;脚本的定位是"开代理后一键检测",引入虚拟环境反而破坏了这个体验。
  2. 自动加 --break-system-packages:Homebrew 官方 STRONGLY 不推荐,可能污染系统 Python,不能作为默认行为。
  3. 脚本内部建 venv 再装依赖:实现复杂、跨平台坑多(路径、权限、清理)、首次运行体验差。
  4. 移除 requests 依赖:脚本里一共只有 3 处 requests.get(url, params=..., timeout=...).json(),标准库 urllib.request + json 几行就能覆盖,且 Python 3 自带。一次性根治,用户侧零感知。

最终选 4。requests 带来的便利(连接池、session、重试)本脚本根本用不到,为这点便利换来 PEP 668 摩擦不划算。

Windows-only 的 colorama / tzdata 保留了 pip 安装路径,但做了两点加固:

  • 安装依次尝试 普通 → --user--break-system-packages --user,覆盖 Windows 上 Store 版 Python 等类似受限场景;
  • 装不上时只打印一行提示后继续运行(彩色输出降级为无色、时区比对降级为仅比 UTC 偏移),不再 sys.exit(1),保证核心功能始终可用。

Changes

  • ip_check.py:新增 _http_get_json 工具函数,替换三处 requests.get(...).json()get_public_info / get_ip_risk / get_stopforumspam)。
  • _pip_install:依次尝试 普通 / --user / --break-system-packages --user,并在 ensurepip 引导后再试。
  • _ensure_deps:只保留 Windows 下的可选增强包检测;所有失败路径改为降级提示,不再 sys.exit(1)

Test plan

  • macOS (Homebrew Python 3.14) 上直接 python3 ip_check.py 运行成功,输出与原版一致。
  • python3 -c \"import ast; ast.parse(open('ip_check.py').read())\" 语法校验通过。
  • Windows 下验证 colorama / tzdata 的安装回退路径(未本地验证,逻辑层面兼容原有行为)。
  • Linux(Debian/Ubuntu 新版 PEP 668 系统 Python)运行验证。

🤖 Generated with Claude Code

- Replace `requests` with stdlib `urllib.request` so the script runs
  with zero third-party deps on Linux / macOS, avoiding the PEP 668
  "externally-managed-environment" failure on Homebrew Python 3.11+
  and recent Debian/Ubuntu.
- Make remaining installs (Windows-only `colorama` / `tzdata`) retry
  with `--user` and `--break-system-packages --user`, and degrade
  silently instead of exiting when install still fails.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant