一次“虚拟环境复制引发的血案”:记一次 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 时间。

相关推荐
想会飞的蒲公英16 分钟前
TF-IDF + 随机森林中文文本分类全链路实战:从训练脚本到 Flask API + Streamlit 前端
人工智能·pytorch·python·随机森林·分类·flask·tf-idf
FriendshipT24 分钟前
Ultralytics:解读C3模块
人工智能·pytorch·python·深度学习·目标检测
极光代码工作室25 分钟前
基于深度学习的异常行为检测系统
人工智能·python·深度学习·神经网络·机器学习
承渊政道26 分钟前
【Python学习】(了解Python背景知识、搭建 Python 环境以及安装PyCharm)
python·学习·pycharm·搭建python环境
川石课堂软件测试28 分钟前
性能测试|Nginx中间件监控与调优
linux·python·nginx·中间件·单元测试·压力测试·harmonyos
Lyn_Li9 小时前
扫描 PDF 歪了怎么办?用 6 种检测方法做本地批量扶正(附开源工具)
python·pdf·ocr·tesseract·开源工具·文档处理·本地处理·扫描件纠偏
金銀銅鐵10 小时前
费马小定理
python·数学·算法
疋瓞14 小时前
python和C++对比(1)_数据类型和数据结构
数据结构·c++·python
如此这般英俊15 小时前
手搓Claude Code-第六章 subagent
数据结构·人工智能·python·语言模型·自然语言处理
元Y亨H16 小时前
Python - FastAPI 全方位介绍
python·fastapi