零到全栈(什么是 API:从亲手调用到备齐环境)

发布时间:2026/9/27 19:53:15
零到全栈(什么是 API:从亲手调用到备齐环境) 究竟什么是 APIAPI 这个词今天几乎无处不在——AI、Agent、大模型、天气、地图……张口就来听起来很神秘这里不解释、不打比方直接拿两个真的 API 来亲手调用一下就明白了从生活中说起不止一个人问过究竟什么是 API比如有位朋友他听说 Claude 特别厉害想用一下找了个渠道说提供 API就跑来问这个 API 是什么意思从这里开始进入后端部分就从 API 讲起理解它特别重要无论想做 web 开发、手机 app 开发还是想认真理解 AI 时代这些新东西几乎都绕不开——有的 API 能查天气有的能拿到大模型的回复有的能帮我们做计算它无处不在而且正好走到这儿了还记得吗文字实验室那一页点 开始分析 是没反应的拼音和情感分数都是写死的假数据要让它真的能算就得给网站补上一个 后端而前端和后端之间怎么对话靠的也是 API有人讲 API 时爱打比方比如把它比作餐厅的后厨——这种比喻有时适得其反反而让人更迷糊理解 API 最快的方式就是亲自找一个调用一下调完你自己就知道它是什么了如果还能自己做一个那就完全通透学任何概念类的东西都是这样没用过很难解释用过一两次就不需要解释那就先找一个 API 用一下第一个查一下你自己的公网 IP先调用一个零门槛的——不用注册、不用花钱、不用申请任何东西有一个网站 ipify.org它是一个免费开放的服务只干一件事告诉你此刻的公网 IP 是多少公网 IP 就是你在互联网上的 地址前面讲过。主页上显示的那个 IP就是你现在的 IP 地址除了网页它还提供 API 服务先介绍一个新的终端命令curl——一个在终端里发网络请求的小工具平时用浏览器访问网址其实用终端也可以访问curl 就是在命令行里访问一个网址时用的它会把服务器原样返回的内容直接打印出来特别适合试 APImacOS 和大多数 Linux 都自带打开终端把下面这行粘进去回车curl https://api.ipify.org?formatjson网址用引号括起来——也可以不用但因为网址里有?这样的符号终端可能会误解加上引号最稳妥意思是告诉终端 这一整串都是网址回车之后很快终端里回来一小段 JSON{ ip: 114.86.123.45 }就这么一句没打开任何网站就问到了自己此刻的公网 IP——就是 ip 那个字段你看到的会是你自己的 IP整个响应就一个字段干干净净这个请求简单到可以直接把那串网址粘进浏览器地址栏回车看到同样的一段数据——这也顺带说明一件事平时用浏览器打开网址本质上也是在向服务器 发请求、拿响应刚才做的这件事就叫 调用 ipify 的 API第二个调用 DeepSeek 的 API再调用一个不一样的。这次不是 查一份数据而是调用 DeepSeek 的大模型让它回一句话这个稍微有点门槛因为对方得知道 是谁在调一来算用量二来防止被乱用所以要先拿一把 身份钥匙 ——API Key注册 / 登录 DeepSeek 开放平台platform.deepseek.com找到 API keys 页面点击创建 API keys起一个名字就能创建一个 API key——得到一串以sk-开头的字符串复制存好只完整显示这一次DeepSeek 的 API 按用量计费需要充一点点余额——别担心就调用几次一次花不了几分钱完整、最新的说明以官方文档为准api-docs.deepseek.com/zh-cn/照着别人的文档用上别人的能力——这本身就是这里想让你体会的事如果此刻实在不想充值可以先跟着往下读、把道理看懂但强烈建议亲手调用一次那种 我居然直接用上了大模型 的感觉非常值得拿到 key 后看 接口文档里面提供了用 curl 调用对话 API 的示例curl https://api.deepseek.com/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer ${DEEPSEEK_API_KEY} \ -d { model: deepseek-v4-pro, messages: [ {role: system, content: You are a helpful assistant.}, {role: user, content: Hello!} ], thinking: {type: enabled}, reasoning_effort: high, stream: false }把示例里的${DEEPSEEK_API_KEY}换成刚复制的那段sk-开头的 key其他部分建议把 Hello! 改成别的 prompt比如 你好请用一句话介绍你自己{role: user, content: 你好请用一句话介绍你自己}把改完的示例粘贴到终端回车稍等一下回来的数据里删掉次要字段后大概是{ choices: [ { message: { role: assistant, content: 你好我是 DeepSeek一个由深度求索打造的 AI 助手很高兴为你服务。 } } ] }看到这样的回应就成功了没打开任何网页就在自己的终端里让 DeepSeek 的大模型回了一句话答案藏在 choices → message → content 里——这就是 调用 DeepSeek 的 APIAPI 是设计给计算机程序用的不用 API 也行查 IP 可以直接访问 ipify.org用 DeepSeek 可以开它的网页或手机 app但如果是一个计算机程序想查 IP、想用 DeepSeek 的大模型网页的方式就行不通了——程序总不能每次都去打开一个浏览器所以对程序调用来说最友好的方式就是 API——它的设计本身就是为计算机程序服务的这种 把自己的能力持续地通过一个固定的入口对外提供出去让别的程序来调用 的做法是整个软件世界的通行做法这个对外的入口就是 API英文全称 Application Programming Interface应用程序编程接口API 的格式标准把刚才两次调用放在一起看两个 API 功能不同但调用方式几乎一模一样——向一个 URL 地址发起请求api.ipify.org、api.deepseek.com发请求时按对方的要求带上该带的信息没有要求可以不带对方在它自己那边处理我们看不见、也不用管它回给我们一段数据一般是 JSON这就是 API 的形态只要按它规定的方式来请求就能用上它的能力完全不需要知道内部怎么实现——这就是 API 的意义让能力可以被别人 对接 过去用不过上面两个案例用了两种请求方式查 IP 那次是取数据叫 GETDeepSeek 那次需要提交内容叫 POSTGET 和 POST 是 API 最常用的两种请求方式但标准不止这两种还有 PUT、DELETE 等遇到时再介绍当 API 有了格式标准我们就不必在意对方用什么语言实现只要按规范请求、按规范响应调用方和提供方都可以用任意语言或框架所以我们用 DeepSeek 的 API不需要关心它是用 Python 还是 C 写的DeepSeek 也不关心我们的请求是 curl 发的还是 Python 发的为什么 AI 时代到处都是 API理解了这一点就能解除 AI Agent 的 神秘感平时用的各种 AI 产品很多本质上就是在调大模型的 API——把我们的话包装一下发过去把答案拿回来再包装成好看的界面那些看起来无所不能的 AI Agent本事来自一件件 工具凡是要联网用别的服务的——查天气、查快递、搜网页、往群里发消息、再喊另一个大模型帮忙……基本都是在调 API另一些则是直接在你电脑上跑命令、读写文件严格说不算网络 API但骨子里是一回事照着一个固定的接口去调用别人已经做好的能力换句话说AI 工具之所以看起来无所不能就是因为它在不停地调用各种现成的能力——其中很大一部分就是 API理解了 API就揭开了这些工具神秘面纱的一大半回到我们的网站前端调后端也是调 API我们自己的项目马上要用到一模一样的逻辑到目前为止网站只有前端——用户在浏览器里看到、点到的那些页面前端很擅长展示和交互但文字实验室那个 根据你输入的文字算出情感分数和拼音前端干不了需要一个专门负责计算和处理的程序——这就是后端那前端怎么把 用户输入的文字 交给后端、又怎么把 算出的分数 拿回来答案就是给自己的网站也做一个 API——就像 DeepSeek 那个 /chat/completions 一样只不过这个 API 是我们自己写的、专门算拼音和情感分数的到时候前端向我们自己的 API 发一个请求带上用户输入的文字后端算完回一段 JSON里面既可以包含拼音也可以包含情感分数你看和你刚才调 DeepSeek 是同一回事。接下来几节要做的就是给网站补上一个后端并写出我们自己的 API那 后端 到底是个什么东西既然反复提到后端有必要把这个词解释一下前端跑在用户的浏览器里负责看得见的展示和交互后端一个一直运行、守在服务器上、等着接收请求的程序负责看不见的计算、处理以及把数据存下来刚才 ipify 和 DeepSeek 那两台 一直守着、等你发请求 的程序就是它们的后端我们的请求发过去它们接住、处理、回话接下来要为自己的网站做的就是这样一个相比之下小得多的后端而 API就是前端用来调用后端的那个入口后端可以用很多种语言写做一个能对外提供 API 的后端用什么编程语言都能做JavaScript (Node)、Python、Go、Java、PHP、Ruby、C#……都可以ipify、DeepSeek 的后端各自用什么语言写的我们不知道也不影响调用它们的 API——因为 API 这个入口和它内部用什么语言实现是两回事这里选 Python 来写后端原因有两个一是它的生态比较成熟尤其在算法、数据、AI 这些方向——文字实验室要算的 拼音”和“情感分数”正好能借上这个力二是它的语法对初学者比较友好但有一件事值得记住Python 只是开发 API 的其中一个选择API 这个概念和用什么语言无关装好 Python环境、venv 与第一个程序把 Python 装到电脑上给项目建好自己的专属环境 (venv)跑起第一个 Python 程序、认一认代码结构再动手装一个第三方库 (requests) 用 Python 调一次 API——pip、requirements.txt 一并落地后端要用的环境一次备齐我们需要 Python 了已经亲手调用过两个 API目标也定了接下来用 Python 给网站写一个自己的 API要运行 Python 写的代码电脑上得先有 Python这个感觉应该不陌生做过前端实战的话很容易想到本地运行 JS 代码之前要先装 Node——Vite、Next 那一套都得靠 Node 才能跑起来后端同一个道理先有运行环境再谈写代码前端项目的运行环境是 Node后端用 Python 写运行环境就是 Python这一部分把后端要用的环境一次备齐装 Python安装前可以先确认电脑上是否已经有 Pythonpython3 --version # 打印出 Python 3.x 的版本号就装好了或者Windows 一般输入 python 而非 python3python --version打印出 Python 3.x 的版本号说明已经安装了如果打印出 Python 2.x要注意2.x 官方已不再维护不建议再用无论是否已装过都建议重新安装一下最新版多个不同版本的 Python 可以共存不用担心冲突安装方式和当初装 Node 一样打开 Python 官网下载页 python.org/downloads/下载最新稳定版安装包macOS 是 .pkgWindows 是 .exe双击一路默认下一步装完后重新开一个终端窗口再跑一次版本命令验证python3 和 python为什么 macOS 上敲的命令是 python3 而不是 python和 JavaScript 一样Python 诞生也已有几十年经历过一次不兼容的大版本升级早期几乎所有开发者都在用 Python 2后来官方为修复历史设计问题推出了 Python 3但这次升级并不平滑——Python 3 有不少语法和行为与 Python 2 不兼容这意味着很长一段时间里一台电脑可能需要同时装 Python 2 和 Python 3老项目只能跑在 2 上新项目推荐 3为了避免混淆许多 Linux 和 macOS 系统约定python 指向 Python 2或保留为空python3 明确指向 Python 3——久而久之 python3 成了许多系统和教程里的标准写法不过随着 Python 2 正式停止支持2020 年如今越来越多的系统重新把 python 指向了 Python 3例如 Windows 官方安装器和很多现代 Linux 发行版里直接输入 python 启动的就是 Python 3对我们来说分别试一下哪个能用就用哪个如果电脑里不止一个 Python从没装过 Python 但电脑上却有——这很正常可能是操作系统自带的也可能是以前装别的软件时顺带装上的前面说过一台电脑上可能同时住着好几个 Python那问题来了敲 python3 的时候用的到底是哪一个有一个终端命令可以回答macOS 下输入which python3各系统对照操作系统命令macOSwhich python3Linuxwhich python3 或 command -v python3WindowsCMDwhere pythonWindowsPowerShellGet-Command python 或 where.exe python它会打印出一条路径——这就是此刻敲 python3 时真正被执行的那一个还可以更进一步把候选名单全列出来which -a python3你可能会看到好几条路径每台机器不一样多少不等——排在最前面的那个就是当前生效的一个值得记住的生存技能以后遇到 版本不对 明明装了却找不到 这类怪事第一招就是 which python3macOS / Linux或 where pythonWindows——先搞清楚自己此刻用的是哪一个 Python很多环境问题看一眼路径就真相大白如果某次明确想用某一个版本但它不是 python3 指向的默认版本可以直接在命令里指明版本号比如电脑上同时有 python3.12 和 python3.14默认 python3 指向 3.14% python3 --version Python 3.14.6想用 3.12就不用 python3直接用 python3.12% python3.12 --version Python 3.12.9venv 与环境隔离盘点一下现状电脑里可能住着好几个 Pythonpython 和 python3 还可能各指各的——每次都要靠 which 确认 现在用的是哪一个这本身就是负担这是版本管理的困境此外还有另一个问题我们需要安装第三方库、工具包而这些包也各有版本以后电脑上不会只有一个 Python 项目它们各自需要的工具包、甚至包的版本都可能不一样——如果全挤在同一份公共 Python 里早晚会打架什么叫第三方库还记得前端的 anime.js 动画库吗那就是 JS 生态里的一个第三方库Python 生态这样的库也非常多几乎肯定会用到所以事情复杂了首先电脑上有不同版本的 Python不同项目可能依赖不同版本其次每个项目还各自依赖不同版本的工具包前端依赖讲过一条规矩——依赖应该跟着项目走每个项目有自己的 node_modulesPython 项目应对同样的处境也有相似的方案Python 官方的解法是别在系统那堆 Python 里纠结给每个项目配一套自己专用的环境——术语叫虚拟环境virtual environmentPython 自带了一个做这件事的工具叫 venv一个示例假设一个项目在 ~/project_A需要 Python 3.12进入项目目录创建一个 .venvcd ~/project_A python3.12 -m venv .venv这个 .venv 是一个目录它帮我们管理当前目录的 Python 环境——用哪个版本的 Python、装了哪些第三方包、各是什么版本但创建之后还不能立即使用这点和 Node 的 package.json 不同.venv 还需要激活source .venv/bin/activate激活之后终端命令行最前面会自动带上(.venv)标识。此时无论用 python 命令此刻可以用 python 了哪怕之前只能用 python3还是 python3都只会指向 Python 3.12安装第三方库时也只会装到 ~/project_A 这个项目的 .venv 之中而不是全局如果关闭终端再开一个新的(.venv) 就消失了虚拟环境也就退出了也可以不关终端显式退出deactivate常见疑问两个项目的虚拟环境目录都叫 .venv激活后都显示 (.venv)怎么区分目录不是必须叫 .venv但这是约定俗成的名称许多配套工具例如 VS Code都认得它尤其是 AI 认得它不建议变更想让提示符不同可以在创建时给它一个自定义提示符python3 -m venv --promptproject_A .venv这样 venv 目录名仍是 .venv但终端上看到的不再是 (.venv) 而是 (project_A)已经在用 miniconda / anaconda 了接下来怎么用 venv如果每次打开终端命令行最前面都有一个(base)提示符那大概率说明你已经在用 miniconda / anaconda统称 condaconda 也能管理 Python 虚拟环境如果你已经在用 conda就不再建议换用 venv 混着管——两者是完全不同的环境管理策略conda 实际上是全局安装的用它自己的方式管理多个环境每个环境有自己的名字默认叫 base用户可以自建比如 myenv312每个环境可以装不同的 Python 版本conda 的 侵略性 比较强一旦按官方指引装好每次启动终端它都会跟着启动此时直接输入 python跑的就是 conda 的默认环境 (base)和 venv 不同conda 不会在项目里创建类似 .venv 的目录项目自身不保存它所依赖环境的上下文需要开发者自己记住 哪个项目对应哪个环境从这个角度说在 vibe coding 时代 venv 反而更有优势——AI Agent 可以在项目里明确理解项目的依赖后续都用 venv 管理环境如果你在用 conda 且想改用 venv建议先退出 conda如何退出 conda如果每次打开终端都看到 (base)可以执行下面的命令关闭 conda 的自动启动conda config --set auto_activate_base false有个版本差异要注意较新版本的 conda24.9 及以后把这个配置项改名成了 auto_activate所以新版也可以写成conda config --set auto_activate false新版用 auto_activate_base 仍然有效只是会多打印一句 该项已弃用 的警告两条命令哪条不报错就用哪条——旧版认前者新版两者都认。执行之后关闭终端再打开就不会看到 (base) 了以后启动终端也不会默认进入 conda 环境这条命令只是不再默认启动 conda并不代表 conda 被移除以后需要时用 conda activate 重新进入用 conda deactivate 退出在项目中创建后端目录和 .venv环境问题搞定回到自己的项目创建一个后端目录用 Python 小试牛刀给后端代码安个家就放在贯穿全程的项目里cd ~/zero-to-tech mkdir backend cd backend这里可能冒出一个问题后端有了 backend/ 目录要不要也建一个 frontend/、把前端挪进去弄得对称一点这里选择不挪新起的全栈仓库确实常见 frontend/ 和 backend/ 并列但我们这个仓库不是设计出来的是长出来的它从一个静态页开始一路长成 React、再长成 Next前端占着根目录是它成长的年轮——这也是真实老项目的常态结构带着历史痕迹只要不碍事就不为了对称而重构现在它一点都不碍事前端在根目录照常 npm run dev后端在 backend/ 里各干各的互不打扰而且之前配好的 Nginx 也全部继续有效哪天真碍事了比如要把前后端拆成两个仓库再挪不迟——到那时你已经有能力自己挪了顺便这也回答了 前后端的独立体现在哪不在目录的组织方式上而在两个独立的进程、两套独立的依赖、两种独立的部署方式上——接下来会挨个碰到然后在 backend/ 里创建虚拟环境顺手用上刚学的 --prompt起个一眼能认出的名字python3 -m venv --promptzero-to-tech .venv执行完ls -a看一眼——多了一个 .venv 文件夹。它就是虚拟环境本身里面放着一份专属于这个项目的 Python还有一个叫 pip 的工具——干什么的等真正需要的那一刻再说建好了先激活source .venv/bin/activate注意看提示符前面多了一个(zero-to-tech)(zero-to-tech) liboMac backend %这个括号在提醒你你现在用的是这个项目自己的那套 Python空口无凭拿刚学的 which 验证一下which python # → /Users/你的用户名/zero-to-tech/backend/.venv/bin/python which python3 # → /Users/你的用户名/zero-to-tech/backend/.venv/bin/python3两条路径都指进了 .venv——刚才那一堆候选 Python 带来的混乱在这个项目里就此终结python 和 python3 指向同一份就是项目自己的这份再无悬念想退出来的时候一个词deactivate提示符前的zero-to-tech消失你又回到了系统环境感受完就再 source .venv/bin/activate 回来从今往后给自己立个习惯进这个项目干活先激活Windows 的同学激活命令是 .venv\Scripts\activate其余一致一个小工具VS Code 有微软官方的 Python 扩展左侧 扩展 面板搜 Python装微软出的那个——它同时负责 Python 的语法高亮、补全、调试第一次写 Python 建议装上装好后它会自动认出项目里的 .venv以后在 VS Code 里新开终端它会自动帮我们激活环境顺手立一条规矩.venv 不进 Git它和 node_modules 一个性质——本地生成、体积不小、随时可重建在项目的 .gitignore 里加上一行backend/.venv/第一个 Python 程序环境好了写一个程序运行一下用 Python 生成一段 JSON为什么是 JSON回想上一部分——API 回给调用方的基本都是 JSON这正是我们的后端马上要天天干的事确认自己还在 backend/ 目录、提示符带着 (zero-to-tech)用 VS Code 打开这个目录新建一个文件 first_json.py写入import json site_name zero-to-tech def make_data(): data {message: hello, world, from: site_name} return json.dumps(data) print(make_data())回到终端运行它运行前先确定当前目录下有这个文件python3 first_json.py终端打印出{message: hello, world, from: zero-to-tech}一段 JSON 出来了——说明 Python 运行环境已经好了可以看到运行一个 Python 程序就是 一条 python3 命令 一个 .py 文件就这么直接不用构建、不用编译、不用浏览器以前 JS 代码靠浏览器跑现在 Python 代码靠 python3 跑顺着这几行代码认一认 Python先说清楚这不是语法课——有 AI 的时代语法可以边用边查我们真正需要的是认得结构看到一段 Python 代码知道它大致的写法看不懂也没关系刚才这个程序虽然短短几行但已经是比较典型的 Python 代码文件从上往下看引入库import json第一行通过 import 引入一个 json 库Python 安装时就自带一大批现成的工具统称标准库——要用哪个import 一下就能用不用另外安装这个 json 是标准库的一员作用是处理 JSON 这种格式常见的标准库成员还有datetime——日期和时间random——随机数os——和操作系统打交道文件、路径、环境变量http.server——一个能接收网络请求的小服务器注意这个马上会用到有标准库自然就有第三方库——不是 Python 自带、而是世界各地的开发者写好后发布到网上的库用第三方库要先安装才能 import这套逻辑前端见过anime.js 就是用 npm install 装回来的第三方库Python 的第三方库装到哪儿你今天已经准备好答案了——装进 .venv 这个项目专属的环境里怎么装下一段就装一个、用一个变量site_name zero-to-tech第二行定义了一个叫 site_name 的变量值是 zero-to-tech——写法很容易理解就是直接的 名字 值函数以及缩进def make_data(): data {message: hello, world, from: site_name} return json.dumps(data)def 用来定义函数注意函数体是靠缩进表示的——这是 Python 最显眼的规矩JS 用花括号{}圈定代码块Python 里缩进本身就是语法哪些行缩进对齐哪些行就属于同一块函数里最后一行是 return表示这个函数最终给出的结果打印print(make_data())print 的意思是在终端上打印显示内容——这一行就是把 make_data() 的结果打印到终端也就是把函数里定义的 data 以 JSON 格式打出来装第一个第三方库用 Python 调一次 APIfirst_json.py 里的 json 是标准库import 就能用但让 Python 真正强大的是海量的第三方库。光说不练假把式——这就装一个、用一个顺便把 pip 和依赖清单一次讲透装什么好呢还记得用 curl 查公网 IP 吗那件事 Python 也能做新建一个 api_demo.pyimport requests resp requests.get(https://api.ipify.org?formatjson) print(resp.json())requests 是 Python 世界最有名的第三方库之一专门用来发网络请求——可以把它理解成 代码版的 curl跑跑看python3 api_demo.py结果不是 IP而是一段报错ModuleNotFoundError: No module named requests报错是线索这句话会一直强调它说得很直白找不到 requests 这个模块——因为它不是标准库Python 没自带得先装pip装第三方库的工具装 Python 第三方库的工具叫 pip——装 Python 时就一起装好了就是后端世界的 npm前端用 npm install 装过 anime.js现在轮到 pip install先确认自己在zero-to-tech环境里提示符带着括号然后pip install requests一条生存法则从现在记起装包之前先瞄一眼提示符确认zero-to-tech在——最常见的翻车就是忘了激活、把包装到了外面回头一跑代码报 找不到模块人就懵了看它滚动的输出——除了 requests 本身还捎带装了 certifi、charset-normalizer、urllib3、idna 几个你没点名的依赖还有依赖npm 那边如此pip 这边也一样装完问一个最关键的问题——它装到哪儿去了看一眼pip show requestsName: requests Version: 2.34.2 Location: /Users/你的用户名/zero-to-tech/backend/.venv/lib/python3.x/site-packagesLocation 那行路径指进了 .venv——正是刚建的那间 项目专属的屋子requests 只住进了这个项目没装到全局环境所以也不会和别的项目打架前面讲了半天 venv 的道理这一刻落到实处了也可以敲 ls .venv/lib/python*/site-packages/亲眼看到 requests 的目录躺在里面现在再跑一次 api_demo.pypython3 api_demo.py{ip: 114.86.123.45}通了我们用 Python 查到了自己的公网 IP——和用 curl 干的是同一件事只不过这回是程序在调 API正是那句 API 是设计给计算机程序用的往后我们自己的后端也可以像这样去调别人的 API眼尖的你可能发现这回打印的{ip: ...}是单引号而刚才 first_json.py 打印的{message: ...}是双引号怎么不一样因为它们其实是两种东西first_json.py 里 json.dumps(...) 产出的是一段 JSON 文本JSON 规定用双引号而这里 resp.json() 直接把返回的 JSON 解析成了一个 Python 字典打印字典时 Python 习惯用单引号字典 ≈ JSON——这个对应关系以后天天见requirements.txt给依赖记一本账现在冒出一个新问题.venv 不进 Git刚立的规矩那别人拿到这个项目之后怎么知道要装 requests或者把代码拉到服务器上之后该怎么安装依赖答案和前端一模一样前端靠 package.json 记依赖Python 靠 requirements.txt生成它pip freeze requirements.txtcat requirements.txt 看一眼certifi2026.6.17 charset-normalizer3.4.8 idna3.18 requests2.34.2 urllib32.7.0每个包一行版本号钉得死死的连那几个 依赖的依赖 也一并列上了以后任何人拿到项目一条命令就能装齐一模一样的环境pip install -r requirements.txt这就是后端版的 npm install和 .venv 相反requirements.txt 要进 Git——它是项目的一部分得跟着代码走到上服务器需要装依赖的时候这份清单的价值就体现了又凑齐一组 角色对应前端后端一一对上前端后端干的活npmpip装第三方包node_modules/.venv/装到哪儿都不进 Gitpackage.jsonrequirements.txt依赖清单都进 Git