一次“虚拟环境复制引发的血案”:记一次 itsdangerous 版本混乱排查全过程

摘要 :不要复制带 venv 的项目文件夹!否则你会在"pip 显示 1.1.0,Python 却跑 2.2.0"的迷宫里绕到怀疑人生。

一次"虚拟环境复制引发的血案":记一次 itsdangerous 版本混乱排查全过程


起因:一个看似简单的注册功能

我正在开发一个 Flask 应用,需要实现用户邮箱确认功能。按照惯例,使用 itsdangerous 生成带过期时间的 token:

python 复制代码
from itsdangerous import URLSafeTimedSerializer

def generate_confirmation_token(self, expiration=3600):
    s = URLSafeTimedSerializer(
        current_app.config['SECRET_KEY'],
        expires_in=expiration,
        salt='confirm'
    )
    return s.dumps({'confirm': self.id})

结果一调用就报错:

css 复制代码
TypeError: __init__() got an unexpected keyword argument 'expires_in'

???不是说 URLSafeTimedSerializer 支持 expires_in 吗?


第一重迷惑:版本到底是什么?

我查了下依赖:

powershell 复制代码
pip list | select-string dang
# 输出:itsdangerous 1.1.0

但为了保险,我在代码里加了打印:

python 复制代码
import itsdangerous
print("REAL version:", itsdangerous.__version__)

输出竟然是:

sql 复制代码
REAL version: 2.2.0

pip 说 1.1.0,Python 说 2.2.0 ------ 我的电脑成精了?

更诡异的是,pip show itsdangerous 一开始显示 1.1.0,后来干脆说"没安装"!


第二重迷惑:路径对不上

运行 pip --version,我以为一切正常:

csharp 复制代码
pip 25.0.1 from c:\projects\shorturl_service\venv\...

等等!我的项目叫 multi-llm,怎么 pip 路径是 shorturl_service

原来......我当初是直接复制了另一个项目 shorturl_service,改名成 multi-llm 的!

而虚拟环境 venv跟着文件夹一起复制过来的 。虽然文件夹名字变了,但 venv 内部所有路径、激活脚本、解释器引用仍然指向"逻辑上的旧项目"

PowerShell 虽然显示 (venv),但底层用的还是 shorturl_service 的环境!

这就导致:

  • 我在 multi-llm 目录下操作
  • pippython 实际作用于 shorturl_service 的 venv
  • 两个项目的包混在一起,版本冲突爆炸

第三重迷惑:包"幽灵式"存在

即使我卸载了 itsdangerous,Python 依然能 import 它!

原因可能是:

  • 通过 pip install -e 可编辑安装过
  • 手动复制过源码到 site-packages
  • .egg-linkeasy-install.pth 残留

pip 根本不知道这个包的存在,但 Python 导入系统能找到它------典型的"游离包"。


终极解决方案:彻底重建虚拟环境

✅ 正确操作步骤:

powershell 复制代码
# 1. 退出当前(错误的)环境
deactivate

# 2. 删除复制来的旧 venv(罪魁祸首!)
Remove-Item -Recurse -Force venv

# 3. 创建全新的虚拟环境
python -m venv venv

# 4. 激活
.\venv\Scripts\Activate.ps1

# 5. 重装依赖
pip install -r requirements.txt

✅ 适配新版 itsdangerous(>=2.0)

既然用新版,就按新版 API 写:

python 复制代码
# 生成 token
s = URLSafeTimedSerializer(secret_key, salt='confirm-email')
token = s.dumps({'confirm': self.id}, expiration)  # 注意:expiration 是 dumps 的参数!

# 验证 token
data = s.loads(token, max_age=expiration)  # 注意:用 max_age!

血泪教训总结

错误做法 正确做法
复制整个项目文件夹(含 venv)并改名 只复制源码,重新创建 venv
相信 pip list 而不验证运行时版本 python -c "import pkg; print(pkg.__version__)" 确认真实版本
忽略 pip --version 的路径 每次激活 venv 后,检查路径是否匹配当前项目
试图"修复"混乱的环境 直接删除 venv 重建,省时省力

最后忠告

虚拟环境(venv)不是普通文件夹,它是和绝对路径绑定的"活体"

复制它,就像克隆一个人却不更新他的身份证号------迟早出问题。

从此以后,我的 .gitignore 里永远有这一行:

复制代码
venv/

而新建项目的第一步,永远是:

bash 复制代码
python -m venv venv

------谨以此文,祭奠我浪费的 3 小时 debug 时间。

相关推荐
清铎几秒前
leetcode_day12_滑动窗口_《绝境求生》
python·算法·leetcode·动态规划
ai_top_trends13 分钟前
2026 年工作计划 PPT 横评:AI 自动生成的优劣分析
人工智能·python·powerpoint
TDengine (老段)22 分钟前
TDengine Python 连接器进阶指南
大数据·数据库·python·物联网·时序数据库·tdengine·涛思数据
brent4231 小时前
DAY50复习日
开发语言·python
万行1 小时前
机器学习&第三章
人工智能·python·机器学习·数学建模·概率论
Data_agent1 小时前
Cocbuy 模式淘宝 / 1688 代购系统(欧美市场)搭建指南
开发语言·python
m0_726365831 小时前
哈希分分预测系统 打造自适应趋势分析「Python+DeepSeek+PyQt5」
python·qt·哈希算法
vyuvyucd1 小时前
Qwen-1.8B-Chat昇腾Atlas800TA2部署实战
python
轻竹办公PPT1 小时前
2026 年工作计划 PPT 内容拆解,对比不同 AI 生成思路
人工智能·python·powerpoint
癫狂的兔子2 小时前
【Python】【Flask】抽奖功能
开发语言·python·flask