pip 装完包 Flask 就起不来:我把虚拟环境和依赖冲突理了一遍

举报
phantomxjc 发表于 2026/09/28 08:49:24 2026/09/28
【摘要】 上周给单位那套Flask监控脚本加个导出Excel的功能,顺手pipinstallopenpyxl。装得很顺利,第二天早上脚本起不来了,报ImportError:cannotimportname'es

上周给单位那套 Flask 监控脚本加个导出 Excel 的功能,顺手 pip install openpyxl。装得很顺利,第二天早上脚本起不来了,报 ImportError: cannot import name 'escape' from 'flask'。

我当时第一反应是 Flask 坏了,于是 pip install --upgrade flask,结果又冒出来 Jinja2 的版本警告。折腾了半个多小时,最后发现问题根本不在 Flask 身上。

先别急着重装,先搞清楚你在用哪个 Python

这台 Windows 机器上装着三四个 Python:系统装的 3.12、WorkBuddy 带的 3.13、还有几个项目各自建的 venv。我平时在命令行里敲的 pip,装到了哪个环境里,其实我自己都不确定。

所以第一步永远是确认:

where python
where pip
python -c "import sys; print(sys.executable)"

python -c "import sys; print(sys.executable)" 这一条最实在,它直接告诉你当前这个解释器是哪个可执行文件,不用猜 PATH 谁排在前面。

还有个坑:PowerShell 里 where 是 Where-Object 的别名,得写 where.exe python,不然命令静默没输出,你会以为没装 Python。

确认完解释器之后,养成一个习惯:永远用 python -m pip install xxx,不要直接 pip install xxx。前者能保证包装到你当前这个 python 底下,后者装到 PATH 里第一个 pip 所属的环境,两者经常不是一回事。

看看冲突到底在哪

我这个报错表面是 Flask 的问题,实际上是某个包把 Jinja2 顶上去了,Flask 版本和新 Jinja2 对不上。

pip check

这条会直接列出不满足的依赖要求,输出很干净。想看得更细就上 pipdeptree:

python -m pip install pipdeptree
python -m pipdeptree --warn fail

--warn fail 只打印冲突部分,不会把整棵依赖树糊你一脸。我看到的是 openpyxl 本身干净,但它带进来的某个传递依赖和既有包版本打架——这就是"装 A 坏 B"最常见的成因。

顺便说一句,装之前可以先试运行,不真装:

python -m pip install --dry-run openpyxl

pip 22.2 以上支持这个参数,它会把要装、要升级的东西都列出来。看到有 "would upgrade flask" 这种字样,就知道要出事了。我后来把这个动作固化成了习惯,装任何生产环境上的包之前先 dry-run 一遍。

venv 不是万能的,但这次确实该用

那套监控脚本之前是直接跑在系统 Python 上的,所有依赖都堆在全局 site-packages 里,谁装个什么都可能踩到别人。

重建一个隔离环境其实就三步:

cd D:\projects\db_monitor
python -m venv .venv
.venv\Scripts\activate
python -m pip install -r requirements.txt

Windows 上要注意两点。一是 PowerShell 默认禁止运行脚本,激活时会报"在此系统上禁止运行脚本",用 Set-ExecutionPolicy -Scope CurrentUser RemoteSigned 改一下就行,改的只是当前用户,不影响机器策略;或者干脆用 cmd 里那个 .venv\Scripts\activate.bat,绕过执行策略。二是激活后提示符前面会出现 (.venv),别嫌它丑,这是唯一能让你确定自己身在哪个环境的信号。

还有个细节:python -m venv .venv 用的是哪个 python,venv 就是哪个版本。想建 3.12 的环境,就得写 C:\...\python3.12.exe -m venv .venv。别指望 venv 自己挑版本,它不会。

requirements.txt 别用 pip freeze 一把梭

我以前的 requirements.txt 是 pip freeze > requirements.txt 生成的,里面躺着四十多个包,一大半是别的项目的。等我要在新机器上还原环境时,那些包全被装上,冲突概率极高。

现在我只写真正直接依赖的那几个,剩下的交给 pip 自己解:

Flask==2.3.3
PyMySQL==1.1.0
openpyxl==3.1.2

如果确实需要锁住传递依赖的版本,用约束文件单独管,和业务依赖分开:

python -m pip install -c constraints.txt -r requirements.txt

这样 requirements.txt 保持干净可读,constraints.txt 负责把版本钉死,两边职责不混在一起。

重装之前,先给自己留个能跑的快照

这次能较快恢复,是因为我前一天恰好做过备份。现在这套流程每次动生产环境前都跑一遍:

python -m pip freeze > requirements.lock.txt

一行命令,十几秒。真把环境搞崩了,重建 venv 之后 pip install -r requirements.lock.txt 就能回到能跑的状态,不用靠记忆去凑版本号。

我现在的顺序基本固定了:先 freeze 留快照,再 dry-run 看影响,确认没问题才真装,装完跑一遍 pip check。多花一分钟,省掉后面半小时的慌乱。

那天最后是把环境整个重建了一遍,只装 requirements 里那三个包,脚本就正常了。escape 那个报错从头到尾都是版本错配的连带反应,跟 Flask 本身一点关系没有。

如果你也遇到"装了 A 之后 B 起不来",别去修 B,先查 A 动了谁。

作者:phantomxjc

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。