文章目录
- 接手Django老项目,我第一步做的不是看代码——环境复现与依赖地狱突围
- 导入语
- 1 ~> 拿到仓库后第一件该做的事——不是 `git clone`
- 1.1 正确的检查顺序
- 2 ~> `requirements.txt` 的暗坑
- 2.1 直接 `pip install -r requirements.txt` 为什么危险
- 2.2 `pip freeze` 的版本锁定问题
- 2.3 我踩过的坑——下架的包
- 3 ~> Python 版本管理——conda vs pyenv vs 直接用系统 Python
- 3.1 为什么不要直接用系统 Python
- 3.2 我的实践
- 4 ~> 数据库驱动——Django 项目的头号环境杀手
- 4.1 `mysqlclient` 的编译地狱
- 4.2 PostgreSQL 的 `psycopg2` 同样问题
- 5 ~> settings.py 中那些硬编码的秘密
- 5.1 数据库密码写死在 settings.py 里——最常见的错误
- 思考 && 总结
- 结尾
接手Django老项目,我第一步做的不是看代码——环境复现与依赖地狱突围
📖文章简介:拿到一个 Django 老项目的仓库地址,新手的第一反应是 clone 下来直接python manage.py runserver——然后迎面撞上ModuleNotFoundError、mysqlclient编译失败、Python 版本不匹配三连击。本文是"接手老项目"系列的上篇,聚焦环境复现的完整流程:从requirements.txt的版本锁定策略到pip freeze的陷阱、从virtualenv到pipenv的演进、从 MySQL 驱动安装的坑到settings.py数据库配置的安全实践。穿插真实经历——接手一个 Python 3.6 的 Django 2.0 项目,光是让它在本地跑起来就花了两天。
🎬 个人主页:源码骑士
❄专栏传送门:《Android开发基础》《python基础课程》
⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂
🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以源码拆解为特色,被读者评价为"看一篇胜过啃一周文档"
导入语
2021 年,我接手了公司一个内部管理系统——Django 2.0 + Python 3.6,最后一次提交是 2019 年 3 月。当时的想法很简单:clone 下来,装依赖,跑起来,看代码。结果从 clone 到runserver成功输出 “Starting development server”,花了我整整两天。
原因不是代码复杂——而是环境。Python 3.6 在 2021 年已经不好装了,mysqlclient在 Windows 上编译需要 Visual C++ Build Tools,requirements.txt里还有两个包已经从 PyPI 下架了。你以为的核心工作是"看代码",实际上的核心工作是"让代码跑起来"。
这篇文章是"接手老项目"系列的上篇,专讲环境复现这条路上的坑和正确的趟法。
1 ~> 拿到仓库后第一件该做的事——不是git clone
1.1 正确的检查顺序
# 第一条命令——不是 git clone,不是 pip installgitlog--oneline-20# 看最近 20 次提交,了解项目活跃度和最近改动方向# 第二条命令catREADME.md# 看有没有环境说明(Python版本、数据库类型、部署方式)# 第三条——检查 Python 版本要求catruntime.txt# 或 .python-version# 如果都没有,看 setup.py 或 pyproject.toml 中的 python_requires这三条命令能帮你避免后续一半的坑。我那个 Django 2.0 项目 README 里什么都没写,但我从 git log 看出最后一次提交涉及"升级 Django 1.11 → 2.0"——说明这个项目经历过版本迁移,代码中可能有旧 API 残留。
2 ~>requirements.txt的暗坑
2.1 直接pip install -r requirements.txt为什么危险
# 典型的"老项目" requirements.txtDjango==2.0.13mysqlclient==1.3.14celery==4.2.1redis==3.0.1看起来很正常。但你执行pip install -r requirements.txt之后可能会遇到:
ERROR: Could not find a version that satisfies the requirement mysqlclient==1.3.14 ERROR: No matching distribution found for mysqlclient==1.3.14这个包的这个版本可能在你当前的 Python 小版本上不可用。或者更糟——这个包已经从 PyPI 下架了。
2.2pip freeze的版本锁定问题
pip freeze > requirements.txt只会锁定显式安装的包,不会锁定依赖的依赖。也就是说——你这个项目依赖celery==4.2.1,而 celery 又依赖kombu。两年前kombu的某个版本是兼容的,但今天如果你只锁了 celery 不锁 kombu,pip 会安装最新版 kombu——然后运行时爆炸。
正确做法:用pip-compile(来自pip-tools)或pipenv lock生成完整的依赖锁文件,包括所有传递依赖。
2.3 我踩过的坑——下架的包
2021 年那个项目中有一个django-extended-choices包已经从 PyPI 下架。pip install 报 404。解决方案是——去 PyPI 的历史包网站找到最后一个版本的.tar.gz,手动下载,放到项目目录中,用pip install ./django-extended-choices-1.3.tar.gz安装。
教训:接手老项目时,先不要试图一步到位装所有依赖。先看 requirements.txt 里有几个包你还认识,不认识的上 PyPI 搜一下是否还存在。
3 ~> Python 版本管理——conda vs pyenv vs 直接用系统 Python
3.1 为什么不要直接用系统 Python
$ python3--versionPython3.10.6项目要求 Python 3.6。系统 Python 是 3.10。你直接pip install Django==2.0.13可能装得上,但 Django 2.0 最后支持的 Python 版本是 3.7——在 3.10 上可能有微小的语法变化不兼容。
工具选择:
| 工具 | 适合什么 | 不适合什么 |
|---|---|---|
pyenv | Linux/macOS,轻量,只管 Python 版本 | Windows(不支持) |
conda | 跨平台,连二进制包都能管 | 安装慢,占用空间大 |
pipenv | 自带虚拟环境 + 依赖管理 | 解析依赖慢 |
virtualenv+pip | 最轻量的基础方案 | 自己管理 Python 版本 |
3.2 我的实践
# 第一步:装对 Python 版本pyenvinstall3.6.15# 第二步:创建项目专用的虚拟环境pyenv virtualenv3.6.15 myproject-env pyenvlocalmyproject-env# 第三步:确认版本python--version# 必须输出 3.6.154 ~> 数据库驱动——Django 项目的头号环境杀手
4.1mysqlclient的编译地狱
pipinstallmysqlclient# Windows: error: Microsoft Visual C++ 14.0 is required# Linux: fatal error: mysql.h: No such file or directorymysqlclient是 C 扩展——它需要编译。Windows 上要装 Visual C++ Build Tools(几 GB 的下载),Linux 上要装libmysqlclient-dev。
最快方案(如果不需要严格的 mysqlclient):
pipinstallpymysql# 然后在 Django settings.py 同级目录的 __init__.py 中加:importpymysql pymysql.install_as_MySQLdb()pymysql是纯 Python 实现,不需要编译。但对于生产环境的高并发场景,mysqlclient的性能更好——它是 C 写的。
4.2 PostgreSQL 的psycopg2同样问题
# Linuxsudoaptinstalllibpq-dev python3-dev pipinstallpsycopg25 ~> settings.py 中那些硬编码的秘密
5.1 数据库密码写死在 settings.py 里——最常见的错误
# settings.py——不要把这种代码和项目一起提交到 GitDATABASES={"default":{"ENGINE":"django.db.backends.mysql","NAME":"production_db","USER":"admin","PASSWORD":"MySecret123",# ← 生产密码在代码里"HOST":"10.0.1.50",}}正确做法:
# settings.pyimportos DATABASES={"default":{"ENGINE":"django.db.backends.mysql","NAME":os.environ.get("DB_NAME","mydb"),"USER":os.environ.get("DB_USER","root"),"PASSWORD":os.environ.get("DB_PASSWORD",""),"HOST":os.environ.get("DB_HOST","localhost"),}}环境变量用.env文件管理(python-decouple或django-environ),.env必须加到.gitignore。
思考 && 总结
接手老项目的环境复现有三步优先级:
- 先读 README 和 git log——确定 Python 版本和数据库类型。
- 用版本管理工具(pyenv/conda)装对 Python——别图省事直接用系统 Python。
- 依赖安装从核心包开始(Django 本身)→ 数据库驱动 → celery 等外围服务——逐个排查,别一把梭
pip install -r requirements.txt。
结尾
上篇到这里结束。下篇讲——环境跑起来之后,怎么看懂一个陌生 Django 项目的架构脉络。
源码骑士 — 源码级拆解,从底层看透技术
👀关注:跟博主一起从源码视角深耕底层原理
❤️点赞:让优质内容被更多人看见
⭐收藏:核心知识点存好,随用随查
💬评论:分享你的经验或疑问,一起交流
🔄一键四连:别忘了给博主一键四连!
🗡️寄语:环境是地基,地基打不好,房子再漂亮也白搭。
结语:两天复现一个老项目环境不算慢——重要的是每一步都能定位问题。下篇进入代码层面——urls.py 路由树怎么读。一键四连!