21-接手Django老项目(上)-环境复现与依赖地狱突围

文章目录

  • 接手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 我踩过的坑——下架的包)
    • [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 同样问题)
    • [5 ~> settings.py 中那些硬编码的秘密](#5 ~> settings.py 中那些硬编码的秘密)
      • [5.1 数据库密码写死在 settings.py 里------最常见的错误](#5.1 数据库密码写死在 settings.py 里——最常见的错误)
    • [思考 && 总结](#思考 && 总结)
    • 结尾

接手Django老项目,我第一步做的不是看代码------环境复现与依赖地狱突围

📖 文章简介: 拿到一个 Django 老项目的仓库地址,新手的第一反应是 clone 下来直接 python manage.py runserver------然后迎面撞上 ModuleNotFoundErrormysqlclient 编译失败、Python 版本不匹配三连击。本文是"接手老项目"系列的上篇,聚焦环境复现的完整流程:从 requirements.txt 的版本锁定策略到 pip freeze 的陷阱、从 virtualenvpipenv 的演进、从 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-decoupledjango-environ),.env 必须加到 .gitignore


思考 && 总结

接手老项目的环境复现有三步优先级:

  1. 先读 README 和 git log------确定 Python 版本和数据库类型。
  2. 用版本管理工具(pyenv/conda)装对 Python------别图省事直接用系统 Python。
  3. 依赖安装从核心包开始 (Django 本身)→ 数据库驱动 → celery 等外围服务------逐个排查,别一把梭 pip install -r requirements.txt

结尾

上篇到这里结束。下篇讲------环境跑起来之后,怎么看懂一个陌生 Django 项目的架构脉络。

源码骑士 --- 源码级拆解,从底层看透技术

👀 关注:跟博主一起从源码视角深耕底层原理

❤️ 点赞:让优质内容被更多人看见

收藏:核心知识点存好,随用随查

💬 评论:分享你的经验或疑问,一起交流

🔄 一键四连:别忘了给博主一键四连!

🗡️ 寄语:环境是地基,地基打不好,房子再漂亮也白搭。

结语:两天复现一个老项目环境不算慢------重要的是每一步都能定位问题。下篇进入代码层面------urls.py 路由树怎么读。一键四连!

相关推荐
金銀銅鐵1 小时前
用 Tkinter 实现简单的 15 puzzle
后端·python
Dylan的码园1 小时前
python基础与快速入门
开发语言·python
Rain5091 小时前
2.4. PostgreSQL 数据库连接与实战指南
前端·数据库·人工智能·后端·postgresql·数据分析
石榴树下的七彩鱼1 小时前
图片去文字接口,支持去除图片中的文字(附 Python / Java / PHP / JS 示例)
java·python·php·api接口·图片去水印·ai图片修复·图片去文字
极光代码工作室1 小时前
基于机器学习的新闻分类系统
人工智能·python·深度学习·机器学习
枫叶v.1 小时前
Agent 开发架构:从增强型 LLM 到可运维的自治系统
开发语言·python
winfredzhang6 小时前
用 MediaPipe 手势数字识别一键打开下载夹里的图片(Python + OpenCV 实战)
人工智能·python·opencv·google·mediapipe
阿维的博客日记8 小时前
Hippo4j 线程池监控平台部署手册
java·spring boot·后端
万少10 小时前
AtomCode开发微信小程序《谁去呀》 全流程
前端·javascript·后端