:::warning 如果你在本篇遇到任何的网络问题或疑似网络问题,请向学长私聊求助。 :::
工欲利其事,必先利其器。Lab 0 中我们会进行基础的开发环境搭建,并补全一些你可能不知道的 Python 知识。
概念普及
这一小节给大家普及本篇文档可能你会遇到的陌生词语
Linux? 发行版(distro)?
Linux 严格意义上指的是 Linus Torvalds 最初编写的那个系统内核(kernel)。一个“能用的操作系统”= 内核 + 一堆用户态工具(命令行工具、包管理器、桌面环境…) + 配置 + 生态整合。不同的社区或公司,会在同一个 Linux 内核基础上,搭建并打包自己的“发行版”(distribution, 简写 distro)。
常见发行版:Ubuntu、Debian、Fedora、Arch、openSUSE、CentOS / Rocky / Alma、RHEL 等。它们的差异主要体现在:
- 包管理器不同(Ubuntu 用 APT,Fedora 用 DNF,Arch 用 pacman)
- 默认预装的软件 & 配置不同
- 软件版本策略(偏“新”还是偏“稳”)
- 社区/企业支持方式(社区滚动更新 vs 企业长期维护 LTS)
你现在在 WSL 装的 Ubuntu,就是“Ubuntu 发行版”。说“我用的是 Linux”通常在实际语境里=“我用的是某个 Linux 发行版”。
:::tip 什么时候需要关心“发行版差异”? 写/跑代码 -> 几乎不用纠结;部署生产、写系统级脚本、看教程命令对不上时 -> 才需要意识到“也许是发行版不一样”。 :::
:::warning 小坑
网上复制的命令如果带 yum
/ dnf
/ pacman
而你系统里只有 apt
,不要怀疑人生——只是发行版不一样,换成对应包管理器就好。
:::
Shell? 终端(Terminal)?
Terminal(终端)是一个“窗口/程序”,负责把你敲的字符传给后面真正执行命令的“Shell”,再把结果展示出来。Shell 则是“命令解释器”——接收你输入的文本命令,解析、执行,然后输出结果。
类比:
- 终端 = 聊天窗口
- Shell = 正在和你对话、帮你办事的“客服”
常见 Shell:bash、zsh、fish、powershell(不是 Linux 传统 shell 但理念类似)。你在 WSL 里默认启动的一般是 bash;很多开发者会换成更好用(补全更强/主题更丰富)的 zsh + oh-my-zsh。
如何知道自己当前 shell?
|
|
:::tip
“我打开 VS Code 内置终端”“我在 Windows Terminal 新建了一个标签页”——这些动作都是在启动一个“终端程序实例”;里面跑的那一行提示符(veno@pc:~$
)背后那个解释命令的才是 shell。
:::
:::warning Ctrl+C
在 shell 中 Ctrl + C
不是复制,是“向前台进程发送中断信号”(终止当前正在运行的命令)。复制请用 Ctrl + Shift + C
(在大多数终端里)。
:::
包管理器
包管理器(package manager)= “下载/安装/升级/卸载 软件/库 的自动化工具 + 依赖关系解决器”。
举些例子:
操作系统层面:
- Ubuntu: apt (
sudo apt install xxx
), snap… - Fedora: dnf
- Arch: pacman, yay, paru
- 。。。
编程语言生态层面:
- Python: pip / (最推荐的) uv / poetry / pdm
- Node.js: npm / pnpm / yarn
- Rust: cargo
- 。。。
为什么需要包管理器?
- 自动解决依赖:安装 A 顺便装它需要的 B/C
- 版本管理:指定版本/锁定版本避免“昨天能跑今天炸”
- 统一卸载:不会在系统角落留下一堆孤儿文件
虚拟机和容器
虚拟机(Virtual Machine, VM)= 在你的物理机器(Host)里,用软件模拟出另一套“硬件”并在其上运行一个“客体操作系统”。常见软件:VMware、VirtualBox、Hyper-V、WSL2(底层也用类似虚拟化能力)。
它解决什么问题?
- 隔离:不同项目/系统互不影响
- 一致性:开发、测试、线上使用一致环境
- 安全:把“可能作死”的尝试关在沙盒里
你可能还见过一个词叫“容器”,简单来说容器就是比虚拟机更轻量更快的系统级隔离工具,同样后端开发中经常用到。
“虚拟机”和“容器” 区别(简化理解):
- 虚拟机:Guest OS 完整存在 -> 较重 -> 启动慢
- 容器:共享宿主机内核,只隔离文件/进程/网络命名空间 -> 轻量 -> 启动快
WSL2 其实就是:微软做的一层“极轻量虚拟机 + 与 Windows 深度整合的文件/网络桥接”。
:::tip “我到底该用 WSL 还是直接装虚拟机?”——写后端/学 Linux → 先用 WSL 足够;需要研究内核、做内核模块、玩系统级实验 → 真 VM, 或者直接装实体机 Linux :::
Python 虚拟环境
Python 虚拟环境 (virtual environment, venv) = 给某个项目准备的一份“隔离的 Python 解释器 + 其 site-packages 目录”。这样不同项目的依赖(版本)互不污染。
为什么必须用?
- 你 A 项目需要
fastapi==0.115.x
,B 项目还停在0.110.x
,全局安装会冲突。 - 线上部署要复现本地依赖组合,需要可复制、可锁定的环境。
常见方式:
- 标准库
python -m venv venv
+source venv/bin/activate
- uv / poetry / pipenv / pdm:在“虚拟环境 + 依赖锁定 + 脚本运行”上提供更高级封装
uv 做了什么?
- 自动创建/复用隔离环境
- 解析
pyproject.toml
里声明的依赖 - 生成/使用锁文件(
uv.lock
)保证团队一致
:::tip 判断当前是否已激活虚拟环境
执行 which python
/ which pip
,如果路径落在项目缓存/虚拟目录里(而不是 /usr/bin/python3
),就说明你在“虚拟”里。或者看提示符是否多了形如 (venv)
的前缀(取决于工具)。
:::
:::warning 常见误区
- “我已经有 WSL 或虚拟机了,还需要 Python 虚拟环境吗?”——需要。系统级环境隔离 ≠ 语言级依赖隔离。
- “直接全局 pip install 不是更简单吗?”——初期简单,后期灾难:版本冲突、无法复现、卸不干净,可能在项目中引入别人没有的依赖也无法发觉。
:::
开发环境配置
Windows 配置流程
安装 WSL2
WSL2 (Windows Subsystem for Linux 2),本质上其实是一个运行在 Windows 的轻量级 Linux 虚拟机。
大多数后端服务最终会部署在 Linux 服务器中,因此对于后端学习,我们最好尽快熟悉 Linux 的命令行操作。
对于 Windows 10 版本 2004 及更高版本(内部版本 19041 及更高版本)或 Windows 11 ,使用以下教程:
对于 Windows 10 老版本(低于上面所说的版本),参考:
上面的微软式中文文档经过一些零基础小白的测试,已经确定会给他们造成一些歧义,而英文不会。你可以选择切换到英文阅读上面给出的官方文档,或者跟着本流程走一遍。
下面我们正式开始 WSL2 的安装。
如果你是 Windows 11, 那么打开你的 Windows 开始菜单,搜索“终端”或“Terminal”或“Windows Terminal”,你应该能搜到这个应用,它是默认附加在 Windows 11 上的。通过这个应用你可以更方便地以标签页的方式开启和管理你的 Shell 窗口,就像浏览器的标签页一样。
我们使用它打开一个管理员权限的 Powershell, 在其中输入:
|
|
如果这里你出现了一些奇怪的报错,比如下图:
403 实际上是 HTTP 状态码 403 Forbidden, 这也是网络报错,请向学长私聊求助。
:::tip
截至编写本教程时,wsl –install 会默认安装 Ubuntu 24.04 LTS 版本。本教程假设你安装的是该版本。
:::
这个指令会自动帮你启用 Windows 的虚拟机平台功能,并安装 Ubuntu 作为 WSL 的默认发行版。安装完成之后,如果可能的话,则会自动启动 Ubuntu, 开始用户名和密码的初始化。
但你大概率之前没有启用过虚拟机平台功能,除非你安装过 VMWare 之类的虚拟机软件。这个时候并不会自动启动 Ubuntu。此时界面应当会类似下图:
此时虚拟机平台功能和 Ubuntu 都已经成功安装,只是因为虚拟机平台功能需要重启电脑才能启用,因此才没有自动启动 Ubuntu 。
我们需要重启电脑,再次打开 Windows Terminal, 在 Powershell 中输入:
|
|
如此即可启动 Ubuntu。你也可以在 Windows Terminal 中将 Ubuntu 添加到下拉菜单快捷启动列表里,以后启动会更方便。
系统将要求你为 Linux 发行版创建“用户名”和“密码”。用户名建议使用3-8个英文小写字符。
此用户名和密码特定于安装的每个单独的 Linux 分发版,与 Windows 用户名无关。
注意,输入密码时,屏幕上不会显示任何内容。这称为盲人键入。你不会看到你正在键入的内容,这是完全正常的。
创建用户名和密码后,该帐户将是分发版的默认用户,并将在启动时自动登录。
此帐户将被视为 Linux 管理员,能够运行
sudo
(Super User Do) 管理命令。在 WSL 上运行的每个 Linux 发行版都有其自己的 Linux 用户帐户和密码。 每当添加分发版、重新安装或重置时,都必须配置一个 Linux 用户帐户。
设置用户名和密码之后,我们正式完成了 WSL 的安装。
注意区分,本文以后的所有命令行操作如果未说明,则默认是在 Ubuntu 的 Shell 环境中运行,而不是 Powershell。
设置镜像源
由于网络原因,我们需要给 Ubuntu 设置软件仓库的镜像源,才能正常安装软件包。
:::tip 网站镜像(mirror sites, mirrors;镜像站点,镜像网站)是指对网站内容的拷贝,这类网站通常具有与原站不同的URL,但托管了相同或者是几乎相同的内容。镜像原意是光学里指的物体在镜面中所成之像。引申到计算机网络上,镜像通常用于为相同信息内容提供不同的源,特别是在下载量大的时候提供了一种可靠的网络连接。 :::
这里我们使用清华大学镜像站。在搜索引擎搜索ubuntu 清华镜像
,你应该可以搜到下面的网站。
ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站
我们使用的是 24.04 LTS。想确认你的 wsl 安装了什么版本的 ubuntu,你可以运行:
|
|
镜像站使用帮助中有这样的描述:
在 Ubuntu 24.04 之前,Ubuntu 的软件源配置文件使用传统的 One-Line-Style,路径为
/etc/apt/sources.list
;从 Ubuntu 24.04 开始,Ubuntu 的软件源配置文件变更为 DEB822 格式,路径为/etc/apt/sources.list.d/ubuntu.sources
。将系统自带的对应文件做个备份,然后根据格式的选择下面对应的内容替换,即可使用选择的软件源镜像。
要备份,其实就是复制一份原文件出来的意思。Linux 中的复制指令是cp
, 即 copy 的缩写。
|
|
之后,选择 DEB882 格式的正确 Ubuntu 版本,复制它生成的配置,替换原来的镜像源文件内容。
|
|
输入指令,你会看到类似这样的界面(文件名没有 .bak
):
:::tip nano 是 Unix 和类 Unix 系统中的一个终端文本编辑器。它通过 Control 键来控制。比如 Ctrl+O 保存当前文件;Ctrl+W 进入搜索菜单。nano 在屏幕底部显示两行快捷键,列出了当前状态下能用的命令。如果要查看完整的列表,可以按 Ctrl+G 进入帮助屏幕。nano同时支持用鼠标点击屏幕下方的快捷键来操作。 :::
下面快捷键提示中的^
指的是 Ctrl,M
是“Meta 键”的缩写,在这里实际上是指 Alt 键。
我们需要删除文件原来的内容,把我们刚刚从网站上复制的配置复制进去。按住 Shift + 方向键下
, 控制光标选中文件全部内容,之后^K Cut
剪切掉。
这里之所以是剪切而不是退格,是因为 nano 中 Backspace 只会删除掉光标之前的一个字符,而不是删除我们选中的内容。删除掉文件原来的内容之后,我们向文件中用Ctrl + Shift + V
粘贴我们刚刚从镜像站复制的配置。
:::warning 注意
这里 nano 使用的粘贴板是独立的,并不是 Windows 的粘贴板,也就是我们不应该使用^U
快捷键粘贴我们复制的配置,我们实际上是通过 Windows Terminal ,将 Windows 的粘贴板内容粘贴到 shell 中。你实际上应该使用的“粘贴”快捷键是 Ctrl + Shift + V
。同样,要复制内容我们也是加上 Shift,即 Ctrl + Shift + C
。
在 shell 中,Ctrl + C
一般是终止进程的快捷键。
:::
正确粘贴之后,内容应该像这样:
接下来保存文件。^O
保存文件,会询问保存的文件名,直接回车保持文件名原样即可。之后^X
退出 nano。
修改完镜像源之后,我们更新软件仓库,保证同步:
|
|
:::tip 有没有觉得这些配置编辑操作相当麻烦?你可以尝试学习使用 vim 编辑器,当你熟练使用之后,我们在终端编辑这种配置文件会比 nano 便捷的多。未来的开发中,我们将不可避免地经常在终端中编辑配置文件。 :::
Python 环境配置
本教程基于 Python 3.12 或更高版本。截止教程编写时,wsl 默认安装 Ubuntu 24.04 LTS ,该版本已经默认安装了 Python 3.12.3。
在 ubuntu 中查看当前的 Python 版本:
|
|
你可能听说过 pip, 它是 Python 基础的包管理器。但现代 Python 开发中我们一般使用更为便捷的包和项目管理器,例如 uv, poetry, pdm 等。本教程使用 uv。
uv 是一个比较新的工具,Ubuntu 软件源不一定包含。我们使用官方的安装脚本:
|
|
如果安装正确,输出应类似下图:
这个输出告诉我们,要使用 uv, 我们需要重启一个 Shell。我们新开一个 Ubuntu 窗口即可。
uv 是一个很强大的工具,建议阅读它的文档,学习使用。
VS Code 配置
本教程使用 VS Code 作为我们的 IDE。
省流:VS Code + WSL 插件 + Python 相关插件
安装 VS Code。下载链接
安装并打开之后,在左侧的插件栏搜索简体中文插件以及 WSL 插件,安装。之后我们就可以在 ubuntu 中使用code
指令打开 Windows 中的 VS Code 了。
我们首先使用 uv 创建我们的第一个 Python 项目:
|
|
:::tip
在文档中,对于多条指令,$
字符一般是为了标识一条指令的开头。偷懒复制粘贴的时候可别把$
也一起复制进去了。
:::
此时 Ubuntu WSL 应该会自动开始安装 VSCode 服务器,并打开一个 VS Code 窗口:
uv 很方便吧?一下就帮我们把项目初始化好了。
之后,我们在 Ubuntu 的 VS Code 中安装我们所需的所有插件。注意你需要把插件安装到 “WSL:UBUNTU”,而不是“本地”。
你至少需要安装:Python, Pylance, Git Graph。你可以自己探索其他好用的插件。
本 wiki 的 C-Start 课程提供的 VS Code 的配置文件中有一套开箱即用的 C/C++ 配置。你可以参考这个配置文件中好用的插件。大多数时候,等到需要写什么格式的文件再装什么插件就行。
Git 配置
Git 用于我们项目的版本控制。现在不熟悉没关系,你暂时只需要记住一些基础操作就行。
首先我们在 Ubuntu 安装 git:
|
|
安装之后,需要先进行一些配置工作。输入以下指令:
|
|
放心,这里的 name 和 email 只是一个标识符,不会真有人给你发验证邮件什么的,填的邮箱不存在也无所谓。在你每次提交代码的时候你都得靠这个标签来说明这个版本是谁提交的。要不然 git 会不让你提交代码。
想学习 Git 的基本操作,你可以看看Learn Git Branching, 闯关式,交互式的 git 教程,很有意思。
关于 Git 和 Github 的更多内容你可以参考旧版 Wiki。
Linux 配置流程
你都装上 Linux 了,该自己动手丰衣足食了(
MacOS 配置流程
我没有 Macbook,等一个有 Macbook 的好心人提一个 PR。
Python 开发知识普及
根据本教程的前置知识要求,你至少已经学会了一门编程语言的基本语法了,或许学的就是 Python。为了以后少走一点弯路,我们在 Lab 0 补齐一些现代 Python 开发的知识。
Type Hint(类型提示)
Python 是一门强类型,动态类型的语言! 虽然 Python 作为解释型语言看起来语法很随意,类型很随意,但它实际上是有严格的类型验证的,只不过和编译语言不同,Python 作为解释型动态类型语言,对类型的检查被放在了运行时。关于这一点。你可以阅读 Stack Overflow - Is Python Strongly Typed?
在后端世界,代码不再是几十行的小脚本了,而是成百上千行,多人协作,需要长期维护的复杂系统。类型注解是一个必须项。
确保你阅读FastAPI 文档 - Python 类型提示简介
通过写类型注解,你可以明确声明各种变量的类型,并让你的 IDE 在编写代码时就帮你检查类型。写代码时候的这点多敲的字永远好过代码上线之后,周末凌晨被叫起来修 bug 的痛苦。并且有类型注解之后,才能利用好 IDE 的自动补全功能,这会极大提高你的开发效率。
基本上除了 Python, 大多数语言都需要你写出明确的类型声明。趁早适应这一点,别被 Python 惯坏了。
现代类型标注写法
教程使用 Python 3.12。我们不是开发一个开源库,也不是维护什么企业历史遗留项目,不需要考虑兼容问题。因此本教程将全面使用现代类型标注写法。
现代写法更加简洁易读,性能更优,并且与现代 Python 后端框架的集成度更好。
上面的 FastAPI 文档中的大多数写法都是兼容到 Python 3.8+。这里我大概列举一下现代写法和旧写法的参照,建议遵循现代写法来写 Python 代码。
联合类型(Union Types)
现代(3.10+): 使用|
操作符
|
|
旧写法:
|
|
标准集合类型
现代(3.9+): 直接使用内置集合类型, 如list
, dict
, tuple
, set
。
|
|
旧写法:
|
|
类型别名
现代(3.12+): 使用type
语句定义类型别名
|
|
旧写法:
|
|
泛型
现代(3.12+): 使用类型参数语法
|
|
旧写法:
|
|
返回自身实例
现代(3.11+): 使用Self
类型
|
|
旧写法处理实例创建的时候会有问题:
|
|
类型注解(Annotated Pattern)
现代(3.9+): 用于给类型附加额外的元数据,主要被 FastAPI、Pydantic、Typer 等现代框架使用,用于实现依赖注入、数据校验等功能。
|
|
旧写法:
|
|
Type Checking
在 VS Code 中 Ctrl + ,
快捷键打开设置,或是从左下角打开设置,搜索 Pylance type checking mode
, 有这样的设置:
开启之后,Pylance 插件会自动检查你的类型问题,在你运行代码前就帮你指出。
随便写点小脚本的时候至少开 standard 或者 basic, 但任何严肃项目都肯定是要开 strict 的。
我的个人习惯是,不管什么时候都开着 strict, 养成良好的代码习惯。