Skip to content

Commit 80f102a

Browse files
authored
Ch07: typo fixes, remove python2, modern tools (#106)
* Ch07: typo fixes, remove python2, modern tools * Ch07: update python2 desc, add link to uv
1 parent f703617 commit 80f102a

File tree

1 file changed

+44
-81
lines changed

1 file changed

+44
-81
lines changed

docs/Ch07/index.md

Lines changed: 44 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ icon: material/xml
99
!!! abstract "导言"
1010

1111
作为一个成熟而实用的系统,我们该如何在 Linux 上进行日常的编程开发呢?
12-
这一章将解答一下几个问题
12+
这一章将解答以下几个问题
1313

1414
- Linux 上的 C/C++ 开发
1515
- Linux 上的 Python 开发
@@ -37,7 +37,7 @@ int main() {
3737

3838
这是一个简单的 Hello World 程序。我们如何使它变为一份二进制可执行文件呢?
3939

40-
在 Windows 或 Mac OS X 这样带 GUI 的系统上,通过安装 IDE,我们可以使用 IDE 中的编译功能来编译出目标。
40+
在 Windows 或 macOS 这样带 GUI 的系统上,通过安装 IDE,我们可以使用 IDE 中的编译功能来编译出目标。
4141
实际上,这些带有图形界面的 IDE 的编译往往是封装了各种提供命令行接口的编译器。
4242
自然,在众多无 GUI 的 Linux 上,我们同样可以调用这些提供命令行接口的编译器进行编译。
4343

@@ -48,8 +48,8 @@ int main() {
4848

4949
Windows 上常见的编译器则是 cl.exe,由微软维护。著名的 Visual C++ (MSVC) 即使用了 cl.exe。
5050

51-
Mac OS X 本身由 BSD 发展而来,也以 gcc 和 clang 为主。
52-
值得一提的是,Mac OS X 上自带的 gcc 其实是 clang 的别名,在 Terminal 输入 `gcc -v` 即可发现。
51+
macOS 本身由 BSD 发展而来,也以 gcc 和 clang 为主。
52+
值得一提的是,macOS 上自带的 gcc 其实是 clang 的别名,在 Terminal 输入 `gcc -v` 即可发现。
5353

5454
这里我们使用 gcc 对这个文件进行编译,生成二进制文件:
5555

@@ -78,7 +78,7 @@ Hello World!
7878

7979
如果你不会,别急,这里将做一个简单的介绍:
8080

81-
假设你拥有一下两个文件
81+
假设你拥有以下两个文件
8282

8383
```c
8484
// main.c
@@ -281,8 +281,7 @@ CMake 作为一个足够成熟、也足够陈旧的工具,既有历史遗留
281281
如果你想了解 CMake 的一些知识,附录将会有简单的介绍,亦可以考虑看一些较新的、关于 Modern CMake 的博客,以及官方的最新文档。
282282

283283
另一个值得一提的是 ninja。ninja 和 Makefile、autoconf 较类似,是构建工具,所属抽象层次低于 CMake。
284-
ninja 的特点的是相较与 Makefile 更快,对于多线程编译的支持更好。
285-
详细信息可以到 ninja 的官方网站查看。
284+
此外,**Meson** 也是近年来非常流行的现代构建系统,它通常配合 ninja 使用,语法比 CMake 更加简洁。
286285

287286
### 至于 C++ {#c-for-cpp}
288287

@@ -311,7 +310,25 @@ Python 作为一门年长但恰逢新春的解释型语言,亦被业界广泛
311310
在 Python 解释器中,Python 代码首先被处理成一种字节码(Bytecode,与 JVM 运行的字节码不是一个东西,但有相似之处),
312311
然后再交由 PVM(Python virtual machine)进行执行,从而实现跨平台和动态等特性。
313312

314-
由于使用过于广泛,几乎每一份 Linux 都带有 Python 解释器,以命令 `python2` 或 `python3` 调用,分别对应两个版本的 Python。
313+
由于使用过于广泛,几乎每一份 Linux 都带有 Python 解释器,以命令 `python3` 调用。
314+
315+
!!! note
316+
317+
部分更早的发行版中会包含 Python 2,且默认将 `python` 命令指向 Python 2。
318+
319+
对于现代的 Linux 发行版,我们建议安装 `python-is-python3` 包,使得 `python` 命令指向 `python3`。
320+
321+
```console
322+
$ sudo apt install python-is-python3
323+
```
324+
325+
但我们仍建议在脚本和 shebang (`#!` 开头的行) 中显式使用 `python3`,以避免上述歧义。
326+
327+
```python
328+
#!/usr/bin/env python3
329+
330+
# rest of the code
331+
```
315332

316333
### 包管理器 pip {#py-pip}
317334

@@ -321,11 +338,10 @@ pip 和 apt 之类的包管理器有相似之处:完成包的安装和管理
321338
不过 pip 管理的是 Python 包,可以在 Python 代码中使用这些包。让我们看下面的例子:
322339

323340
```console
324-
# 安装 Python 3 和 Python 3 的 pip。对于 Python 2 和 3 间的纠纠缠缠,我们将在之后讲解。
341+
# 安装 Python 3 和 Python 3 的 pip。
325342
$ sudo apt install python3 python3-pip
326343

327344
# 测试一下看看,是否能够正常使用它们。
328-
# 请保证在 `python` 和 `pip` 后有 3 这个数字。这也是历史遗留问题。
329345
$ python3 -V
330346
$ pip3 -V
331347

@@ -366,7 +382,7 @@ print(a)
366382

367383
#### requirements.txt {#py-requirements}
368384

369-
在一些项目下,你可能会发现一个名为 `requirement.txt` 的文件,里面是一行行的 Python 包名和一些对于软件版本的限制,例如:
385+
在一些项目下,你可能会发现一个名为 `requirements.txt` 的文件,里面是一行行的 Python 包名和一些对于软件版本的限制
370386

371387
```txt
372388
# requirements.txt
@@ -388,31 +404,13 @@ $ pip3 install -r requirements.txt
388404
#### setuptools: setup.py {#py-setup}
389405

390406
在 PyPI,即 pip 获取 Python 包的来源中,使用 setuptools 是主流选择。
391-
setuptools 不是 Python 官方的项目,但它已成为 Python 打包(packaging)的事实标准
407+
常见状况是目录下会有一个名为 `setup.py` 的文件。要安装依赖,只需执行 `pip3 install .`
392408

393-
常见状况是目录下会有一个名为 `setup.py` 的文件。
394-
要安装依赖,只需:
395-
396-
```console
397-
$ ls
398-
setup.py
399-
$ pip3 install .
400-
```
409+
#### 其他的:pip-tools、pipenv、uv…… {#py-dep-other}
401410

402-
这种方案特点是使用广泛,易于对接,能提供的信息和配置较全,但配置起来也较复杂
411+
Python 有非常多的依赖管理方案。其中 [uv](https://github.com/astral-sh/uv) 是近年来备受瞩目的新工具,它用 Rust 编写,集成了包管理、虚拟环境管理和 Python 版本管理,速度极快,被认为是 Python 工具链的未来
403412

404-
#### 其他的:pip-tools、pipenv…… {#py-dep-other}
405-
406-
pip-tools 可以看作对 requirements.txt 的增强。
407-
它额外提供了 `requirements.dev` 文件,从而完成了对于依赖进行版本锁定的支持。
408-
409-
pipenv 则是一个更加全面的解决方案,它提供了类似于 npm 的配置文件和 lock 文件,对于依赖有非常强的管理功能。
410-
但其完成度和工业中的稳定性尚有待证明。
411-
412-
Python 有非常多的依赖管理方案,某种意义上讲是自带的 pip 管理功能不足所造成的。
413-
一般而言,只需熟悉常用的 requirements.txt 和 setuptools 方案即可。
414-
415-
### Virtualenv {#py-venv}
413+
### Virtualenv 与 venv {#py-venv}
416414

417415
让我们考虑以下情况:
418416

@@ -433,50 +431,24 @@ Python 通过包管理器如 apt 安装的包,默认安装在系统目录 `/us
433431
在一些 Shell(如 zsh)中,`>=` 有特殊含义。
434432
此时上述命令应用引号包裹 `>=` 部分,如 `pip3 install 'a>=2.0.0'`
435433

436-
为了解决这一问题,允许不同软件使用不同版本的包,Python 提供了 Virtualenv 这个工具。
437-
其使用方法如下:
434+
为了解决这一问题,允许不同软件使用不同版本的包,Python 有下面的虚拟环境工具:
438435

439-
一般 Virtualenv 会带在默认安装的 Python
440-
如果没有,可以用 `sudo apt install python3-venv` 来安装
436+
- **venv**:这是 Python 3.3 之后内置的标准模块,通过 `python3 -m venv venv` 即可创建,是目前的官方推荐方案
437+
- **virtualenv**:一个历史更悠久的第三方工具,在 venv 成为标准之前它是事实上的选择,目前在一些复杂场景或旧版本支持中仍在使用
441438

442439
常见的做法是使用 Python 的模块运行来完成在 Shell 中的执行:
443440

444441
```console
445442
$ python3 -m venv venv
446443
```
447444

448-
以上指令中,`-m` 表示运行一个指定的模块,前一个 `venv` 指运行 venv 这个包的主模块 `__main__`
449-
后一个 `venv` 是参数,为生成目录的路径。
450-
这将使 venv 在当前目录下生成一个名为 `venv` 的目录。
451-
452-
在一般的 shell 环境下,我们将使用 `source venv/bin/activate` 来启用这个 venv。
453-
454-
完成以上操作后,你就进入了当前目录下 venv 文件夹所对应的 Virtualenv。
455-
此时,你使用 `pip3 install` 安装的 Python 包将会被安装在 venv 这个文件夹中,
456-
这些包也只有在你 `source venv/bin/activate` 之后才可见,外部无法找到这些包。
457-
通过 `deactivate` 可以退出 Virtualenv,回到之前的环境中。
458-
459-
实际上,由于 Python 是借助一些环境变量来完成包搜索的步骤的,`source venv/bin/activate`
460-
其实是配置了一些环境变量,从而达到目的。这样,就实现了程序间依赖的隔离。
445+
在一般的 shell 环境下,我们将使用 `source venv/bin/activate` 来启用这个 venv。启用后,你使用 `pip3 install` 安装的包将被隔离在当前文件夹中。通过 `deactivate` 可以退出虚拟环境。
461446

462447
### Python 的版本 {#py-versions}
463448

464-
正如我们之前所讲,Python 不是一个新的编程语言。
465-
现在的 Python,最新的版本已到 3.14(截至 2025 年 9 月)。
466-
实际上还在使用中的 Python 版本,主要在 3.9 以上。
467-
468-
Python 2 到 3 某种程度上讲不是变革,实际上 Python 2 和 3 基本可以看作两个不同的编程语言。
469-
在从 2 到 3 的升级中,一方面众多底层语法都发生了改变,使得迁移异常麻烦。
470-
另一方面,由于 Python 2 的盛行,程序 `python` 普遍指向 `python2`
471-
因此当 Python 3 出现时,为了有效区分两者,调用解释器时我们需要特地使用 `python3` 这一指令。
472-
尽管在某些平台(例如 Arch 系 Linux)上,`python` 己经变为指向 `python3`
473-
但考虑到 Ubuntu、CentOS、Debian 等发行版上 `python` 有可能仍指向 `python2`
474-
显式地指定一个版本是更明智的选择。
475-
476-
实际上,Python 2 已在 2020 年初正式宣告停止维护,
477-
现在如果我们要使用 Python,最好使用 3 版本。
449+
Python 2 已在 2020 年初正式宣告停止维护,由于已淘汰多年,所以本教程不再做更多介绍。
478450

479-
而在 Python 3.x 版本中,截至 2025 年下半年,3.9 亦已经 EOL(end of life)
451+
现在的 Python,最新的版本已到 3.14(截至 2025 年 9 月)。实际上还在使用中的 Python 版本,主要在 3.9 以上
480452

481453
!!! tip "我应该选择哪个版本的 Python?"
482454

@@ -509,32 +481,23 @@ Python 2 到 3 某种程度上讲不是变革,实际上 Python 2 和 3 基本
509481

510482
### Python 的其他实现 {#py-implementations}
511483

512-
Python 作为一门编程语言,官方的实现是 CPython,我们一般使用的、成为事实标准的就是这个。
513-
CPython 中的 C 是指此解释器是用 C 实现。
514-
515-
相应的,Python 还有其他的一些实现:
516-
517-
- JPython:将 Python 编译到 Java 字节码,由 JVM 来运行;
518-
- PyPy:相较于 CPython,实现了 JIT(just in time)编译器,性能有极大地提升;
519-
- Cython:引入了额外的语法和严密的类型系统,性能也有很大提升;
520-
- Numba:将 Python 编译到机器码,从而直接运行,性能也不错。
484+
除了官方的 **CPython**,Python 还有其他实现:
521485

522-
视情况使用不同的 Python 实现能够很大程度地提升性能。
523-
但如果你不确定自己的意向,且性能需求不大,使用官方的 CPython 也是明智之选。
486+
- **PyPy**:实现了 JIT(just in time)编译器,性能有极大提升;
487+
- **Cython**:引入了额外的语法和严密的类型系统;
488+
- **Numba**:将 Python 编译到机器码,适合科学计算。
524489

525490
### 总结 {#py-conclusion}
526491

527-
外部包引用和依赖管理是程序开发中必不可少的部分。
528-
如果官方有成熟的方案,跟随他们是明智的选择。
529-
否则则需根据实际情况,按需选用。
492+
外部包引用和依赖管理是程序开发中必不可少的部分。如果官方有成熟的方案,跟随他们是明智的选择。
530493

531494
## 思考题 {#questions}
532495

533496
!!! question "试试 Rust"
534497

535498
Rust 是一门新兴编译型编程语言。
536-
尝试查询 Rust 的文档,指出 Rust 的编译器、依赖管理程序,
537-
介绍一下如何将 Rust 源码变为可执行程序,如何在 Rust 中引用外部包。
499+
尝试查询 Rust 的文档,了解 Rust 的编译器(rustc)、依赖管理程序(cargo)
500+
介绍一下如何将 Rust 源码变为可执行程序,并思考为什么 Rust 的包管理体验通常被认为优于 C++?
538501

539502
## 引用来源 {#references .no-underline}
540503

0 commit comments

Comments
 (0)