文章目录
- 接手Django老项目,我第一步做的不是看代码------环境复现与依赖地狱突围
-
- 导入语
- [1 ~> 拿到仓库后第一件该做的事------不是 `git clone`](#1 ~> 拿到仓库后第一件该做的事——不是
git clone) -
- [1.1 正确的检查顺序](#1.1 正确的检查顺序)
- [2 ~> `requirements.txt` 的暗坑](#2 ~>
requirements.txt的暗坑) -
- [2.1 直接 `pip install -r requirements.txt` 为什么危险](#2.1 直接
pip install -r requirements.txt为什么危险) - [2.2 `pip freeze` 的版本锁定问题](#2.2
pip freeze的版本锁定问题) - [2.3 我踩过的坑------下架的包](#2.3 我踩过的坑——下架的包)
- [2.1 直接 `pip install -r requirements.txt` 为什么危险](#2.1 直接
- [3 ~> Python 版本管理------conda vs pyenv vs 直接用系统 Python](#3 ~> Python 版本管理——conda vs pyenv vs 直接用系统 Python)
-
- [3.1 为什么不要直接用系统 Python](#3.1 为什么不要直接用系统 Python)
- [3.2 我的实践](#3.2 我的实践)
- [4 ~> 数据库驱动------Django 项目的头号环境杀手](#4 ~> 数据库驱动——Django 项目的头号环境杀手)
-
- [4.1 `mysqlclient` 的编译地狱](#4.1
mysqlclient的编译地狱) - [4.2 PostgreSQL 的 `psycopg2` 同样问题](#4.2 PostgreSQL 的
psycopg2同样问题)
- [4.1 `mysqlclient` 的编译地狱](#4.1
- [5 ~> settings.py 中那些硬编码的秘密](#5 ~> settings.py 中那些硬编码的秘密)
-
- [5.1 数据库密码写死在 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 正确的检查顺序
bash
# 第一条命令------不是 git clone,不是 pip install
git log --oneline -20 # 看最近 20 次提交,了解项目活跃度和最近改动方向
# 第二条命令
cat README.md # 看有没有环境说明(Python版本、数据库类型、部署方式)
# 第三条------检查 Python 版本要求
cat runtime.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 为什么危险
bash
# 典型的"老项目" requirements.txt
Django==2.0.13
mysqlclient==1.3.14
celery==4.2.1
redis==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.2 pip 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
bash
$ python3 --version
Python 3.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 我的实践
bash
# 第一步:装对 Python 版本
pyenv install 3.6.15
# 第二步:创建项目专用的虚拟环境
pyenv virtualenv 3.6.15 myproject-env
pyenv local myproject-env
# 第三步:确认版本
python --version # 必须输出 3.6.15
4 ~> 数据库驱动------Django 项目的头号环境杀手
4.1 mysqlclient 的编译地狱
bash
pip install mysqlclient
# Windows: error: Microsoft Visual C++ 14.0 is required
# Linux: fatal error: mysql.h: No such file or directory
mysqlclient 是 C 扩展------它需要编译。Windows 上要装 Visual C++ Build Tools(几 GB 的下载),Linux 上要装 libmysqlclient-dev。
最快方案(如果不需要严格的 mysqlclient):
bash
pip install pymysql
# 然后在 Django settings.py 同级目录的 __init__.py 中加:
import pymysql
pymysql.install_as_MySQLdb()
pymysql 是纯 Python 实现,不需要编译。但对于生产环境的高并发场景,mysqlclient 的性能更好------它是 C 写的。
4.2 PostgreSQL 的 psycopg2 同样问题
bash
# Linux
sudo apt install libpq-dev python3-dev
pip install psycopg2
5 ~> settings.py 中那些硬编码的秘密
5.1 数据库密码写死在 settings.py 里------最常见的错误
python
# settings.py------不要把这种代码和项目一起提交到 Git
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "production_db",
"USER": "admin",
"PASSWORD": "MySecret123", # ← 生产密码在代码里
"HOST": "10.0.1.50",
}
}
正确做法:
python
# settings.py
import os
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 路由树怎么读。一键四连!