在本文中,我们介绍了几个现代化的 Python 工具,它们各自在提升开发效率、代码质量和用户体验方面发挥着重要作用。uv 作为一个高效的 Python 版本管理工具,帮助开发者轻松管理复杂的开发环境;Ruff 通过其速度和易用性,显著提升了代码质量和开发效率;mypy 作为静态类型检查的领先工具,帮助开发者构建更可靠、易维护的代码;Typer 则简化了 CLI 应用程序的开发,结合 uv 的环境管理能力,进一步提升了项目配置和部署的便捷性;最后,Rich 通过美化终端输出,为开发者提供了更直观、美观的调试和展示工具。
这些工具的结合使用,不仅能够显著提升个人开发者的工作效率,还能在团队协作中发挥重要作用,帮助开发者更轻松地构建高质量的 Python 项目。随着 Python 生态系统的不断发展,这些工具将成为现代 Python 开发中不可或缺的一部分。
Python 3.11
Python 3.11 和 3.12 都在性能上有所提升,但我们选择了 Python 3.11,因为 3.12 在一些流行的数据科学库(如 NumPy、Pandas)中仍存在不稳定性,可能影响开发效率和代码可靠性。
对于开发者来说,编程中很大一部分时间都花在了处理错误信息上。Python 3.11 在这方面做出了显著改进,特别是引入了更智能的回溯机制。与以往版本相比,3.11 的回溯信息不仅会显示错误发生的文件和行号,还会在代码片段中明确标出错误的具体位置,甚至高亮显示问题所在的行和列。这种改进大大简化了调试过程,减少了排查错误的时间。
此外,Python 3.11 还优化了错误信息的可读性,使得类型错误(TypeError)或属性错误(AttributeError)等提示更加直观和详细,帮助开发者更快理解问题本质。这些改进不仅提升了开发效率,也降低了新手的学习门槛。
Python 3.11 在性能和错误处理上的改进,使其成为当前开发的理想选择,显著提升了开发者的工作效率和生活质量。
下面的代码有一个错误。我们想为 data 的第一个元素赋值,但代码却引用了一个不存在的变量 datas:
data = [1, 4, 8]
# the variable datas does not exist!
datas[0] = 2
在 Python 3.10 之前的版本中,这会导致错误跟踪,指出变量 datas 不存在:
$ uv run --python 3.9 --no-project mistake.py
Traceback (most recent call last):
File "/Users/adamgreen/data-science-south-neu/mistake.py", line 3, in <module>
datas[0] = 2
NameError: name 'datas' is not defined
Python 3.11 将其诊断向前推进了两步,还提供了一种解决方案,即变量应改名为 data,并指出错误发生在哪一行:
$ uv run --python 3.11 --no-project mistake.py
Traceback (most recent call last):
File "/Users/adamgreen/data-science-south-neu/mistake.py", line 3, in <module>
datas[0] = 2
^^^^^
NameError: name 'datas' is not defined. Did you mean: 'data'?
uv
学习 Python 最难的是学会安装和管理 Python。即使是资深开发人员,也会为管理 Python 的复杂性而苦恼,尤其是当 Python 不是他们的主要语言时。
图片
uv[1] 是一个功能强大的 Python 版本管理工具,旨在简化开发者在本地环境中管理和切换不同 Python 版本的过程。与传统的 Python 版本管理工具(如 pyenv、miniconda 或通过下载安装程序手动安装 Python)相比,uv 提供了一种更加高效和便捷的解决方案。
图片
主要功能
- Python 版本管理:uv 允许用户轻松安装、切换和管理多个 Python 版本。无论是 Python 3.7、3.8 还是最新的 3.12 版本,uv 都能快速响应并下载所需的版本。
- 自动下载与安装:当用户运行指定 Python 版本的命令或脚本时,如果该版本尚未安装,uv 会自动下载并安装所需的 Python 版本。这一功能极大地简化了开发环境的配置过程,避免了手动下载和安装的繁琐步骤。
- 跨平台支持:uv 支持多种操作系统,包括 Windows、macOS 和 Linux,确保开发者可以在不同的平台上使用相同的工具来管理 Python 版本。
- 轻量级与高效:uv 的设计注重性能,启动速度快,资源占用低,能够在不影响系统性能的情况下高效管理多个 Python 版本。
优势
- 简化复杂性:uv 通过自动化 Python 版本的下载和安装,大大减少了开发者在配置开发环境时的工作量。
- 灵活性:uv 不仅支持管理 Python 版本,还可以与现有的虚拟环境工具(如 virtualenv 或 venv)结合使用,提供更加灵活的开发环境管理方案。
- 社区支持:uv 是一个开源工具,拥有活跃的社区支持,开发者可以通过社区获取帮助、分享经验,并参与工具的改进。
下面的命令使用 Python 3.12 运行 "hello world" 程序:
$ uv run --python 3.12 --no-project python -c "print('hello world')"
hello
uv 也是一个用 Python 管理虚拟环境的工具。它是 venv 或 miniconda 的替代工具。虚拟环境允许不同的 Python 安装并存,这样就可以在本地处理不同的项目。
下面的命令创建了一个 Python 3.11 的虚拟环境:
$ uv venv --python 3.11
Using CPython 3.11.10
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
你需要使用 $ source activate .venv/bin 激活虚拟环境。
uv 也是一个管理 Python 依赖关系和软件包的工具。它是 pip 的替代品。Pip、Poetry 和 uv 都可以用来安装和升级 Python 软件包。
下面是一个 uv 管理项目的示例 pyproject.toml:
[project]
name = "hypermodern"
version = "0.0.1"
requires-python = ">=3.11,<3.12"
dependencies = [
"pandas>=2.0.0",
"requests>=2.31.0"
]
[project.optional-dependencies]
test = ["pytest>=7.0.0"]
将 uv pip install 指向我们的 pyproject.toml 即可安装项目:
$ uv pip install -r pyproject.toml
Resolved 11 packages in 1.69s
Installed 11 packages in 61ms
+ certifi==2024.12.14
+ charset-normalizer==3.4.0
+ idna==3.10
+ numpy==2.2.0
+ pandas==2.2.3
+ python-dateutil==2.9.0.post0
+ pytz==2024.2
+ requests==2.32.3
+ six==1.17.0
+ tzdata==2024.2
+ urllib3==2.2.3
和 Poetry 一样,uv 可以将依赖关系锁定到 uv.lock:
$ uv lock
Resolved 17 packages in 5ms
uv 也可以用来添加工具,即全局可用的 Python 工具。下面的命令安装了 pytest 工具,我们可以在任何地方使用它:
$ uv tool install --python 3.11 pytest
Resolved 4 packages in 525ms
Installed 4 packages in 7ms
+ inicnotallow==2.0.0
+ packaging==24.2
+ pluggy==1.5.0
+ pytest==8.3.4
Installed 2 executables: py.test, pytest
这将添加虚拟环境外可用的程序:
$ which pytest
/Users/adamgreen/.local/bin/pytest
Tips: 在 direnv 工具中添加 .envrc,以便在进入目录时自动切换到正确的 Python 版本。
ruff
Ruff[2] 是一个现代化的、高性能的 Python 代码检查和格式化工具,旨在为开发者提供一种更快、更高效的代码质量保障方案。作为 Black、autopep8、Flake8 和 isort 等传统工具的替代品,Ruff 凭借其独特的设计和强大的功能,正在成为 Python 开发者工具箱中的重要一员。
核心特点
- 极速性能:Ruff 的最大亮点是其卓越的性能。由于它是用 Rust 语言编写的,Ruff 在代码分析和格式化方面的速度远超许多基于 Python 的工具。无论是小型项目还是大型代码库,Ruff 都能在几秒内完成代码检查和格式化,显著提升了开发效率。
- 全面的规则覆盖:Ruff 不仅支持 Flake8 规则集的大部分内容,还整合了 isort 等其他工具的规则。这意味着开发者可以通过 Ruff 一次性完成代码风格检查、语法错误检测、导入排序等多种任务,而无需依赖多个工具。
- 高度可配置:Ruff 提供了灵活的配置选项,允许开发者根据项目需求自定义规则集和行为。无论是启用或禁用特定规则,还是调整格式化风格,Ruff 都能轻松满足不同团队和项目的需求。
- 轻量级与易集成:Ruff 的设计注重简洁和易用,无需复杂的依赖或配置即可快速集成到现有项目中。它支持与常见的开发工具(如 VS Code、PyCharm 等)和 CI/CD 流水线无缝集成,帮助开发者在整个开发周期中保持代码质量。
优势
- 速度与效率:Ruff 的极速性能使其在处理大型代码库时表现出色,显著减少了等待时间,提升了开发体验。
- 多功能一体化:Ruff 集成了多种工具的功能,避免了开发者需要在不同工具之间切换的麻烦,简化了工作流程。
- 现代化设计:基于 Rust 的实现不仅带来了性能上的优势,还使 Ruff 更加稳定和可靠,适合现代开发环境的需求。
与现有工具的对比
- 与 Black 相比:Ruff 不仅提供了代码格式化功能,还集成了代码检查的能力,功能更加全面。
- 与 Flake8 相比:Ruff 的速度更快,且支持更多的规则集,同时避免了 Flake8 需要安装多个插件的复杂性。
- 与 isort 相比:Ruff 可以直接处理导入排序问题,而无需额外安装和配置 isort。
图片
下面的代码有三个问题:
- 我们使用了一个未定义的变量 datas。
- 导入的位置不对。
- 导入了我们不用的东西。
data = datas[0]
import collections
在同一目录下运行 Ruff 会发现问题:
$ ruff check .
ruff.py:1:8: F821 Undefined name `datas`
ruff.py:2:1: E402 Module level import not at top of file
ruff.py:2:8: F401 [*] `collections` imported but unused
Found 3 errors.
[*] 1 potentially fixable with the --fix option.
Tips: 在开发过程中,Ruff 在保存文件时运行足够快--确保在文本编辑器中配置了保存时的格式设置
mypy
mypy[3] 是一个强大的静态类型检查工具,专门为 Python 设计,旨在通过引入类型注解和类型检查机制,提升代码的可靠性和可维护性。它允许开发者在 Python 中实现类型安全,从而减少运行时错误,并提高代码的可读性和可维护性。与传统的动态类型 Python 开发方式不同,mypy 提供了一种更接近静态类型语言的开发体验,类似于 TypeScript 对 JavaScript 的增强。
图片
核心功能
- 类型注解支持:mypy 允许开发者在 Python 代码中使用类型注解(Type Annotations),例如变量、函数参数和返回值的类型声明。这些注解不仅提高了代码的可读性,还为静态类型检查提供了基础。
- 静态类型检查:mypy 在代码运行之前对类型注解进行静态分析,检查类型是否一致。它可以捕捉到许多在运行时才会暴露的错误,例如类型不匹配、未定义的属性调用等。
- 渐进式类型:mypy 支持渐进式类型系统,这意味着开发者可以逐步为现有代码添加类型注解,而不需要一次性重构整个代码库。这种灵活性使得 mypy 非常适合在大型项目或已有项目中引入类型检查。
- 与 Python 生态系统的兼容性:mypy 完全兼容 Python 的标准库和第三方库,并且支持许多流行的 Python 框架(如 Django、Flask 等)。此外,mypy 还可以与 IDE(如 VS Code、PyCharm)集成,提供实时的类型检查反馈。
优势
- 提前发现错误:mypy 在代码运行之前就能捕捉到类型相关的错误,避免了运行时崩溃或异常。
- 提高代码可读性:类型注解使代码的意图更加清晰,开发者可以更容易理解函数和类的输入输出类型。
- 增强开发工具支持:mypy 与主流 IDE 和编辑器的集成,提供了实时的类型检查和自动补全功能,显著提升了开发效率。
- 渐进式采用:mypy 允许开发者逐步引入类型注解,无需一次性重构整个代码库,降低了采用的门槛。
mypy_error.py 有一个问题--我们试图将一个字符串除以 10:
def process(user):
# line below causes an error
user['name'] / 10
user = {'name': 'alpha'}
process(user)
我们可以通过运行 mypy 来捕获这个错误--捕获错误而不实际执行 Python 代码:
$ mypy --strict mypy_error.py
mypy_error.py:1: error: Function is missing a type annotation
mypy_error.py:5: error: Call to untyped function "process" in typed context
Found 2 errors in 1 file (checked 1 source file)
第一个错误是因为我们的代码没有类型化 - 我们可以添加两个类型注解,使我们的代码类型化:
- user: dict[str,str] - user 是一个以字符串为键和值的字典、
- -> None: - process 函数返回 None。
def process(user: dict[str,str]) -> None:
user['name'] / 10
user = {'name': 'alpha'}
process(user)
在 mypy_intermediate.py 上运行 mypy,mypy 指出了代码中的错误:
$ mypy --strict mypy_intermediate.py
mypy_fixed.py:2: error: Unsupported operand types for / ("str" and "int")
Found 1 error in 1 file (checked 1 source file)
这是一个无需编写任何特定测试逻辑即可运行的测试。
Tips: 在调试类型问题时,在代码中使用 reveal_type(变量)。mpy 会向你显示它认为变量的类型。
Typer
Typer[4] 是一个基于 Python 类型提示构建命令行界面 (CLI) 的强大工具,旨在为开发者提供一种更简洁、更直观的方式来创建命令行应用程序。与传统的 sys.argv 或 argparse 相比,Typer 充分利用了 Python 的类型注解功能,使得 CLI 的开发更加高效和易于维护。
图片
核心特点
- 基于类型提示:Typer 使用 Python 的类型注解(Type Hints)来定义命令行参数和选项,使得代码更加清晰和类型安全。
- 自动生成帮助文档:Typer 会根据类型注解自动生成命令行帮助文档,开发者无需手动编写复杂的帮助信息。
- 简洁的 API:Typer 的 API 设计非常简洁,开发者只需几行代码即可实现复杂的命令行功能。
- 强大的子命令支持:Typer 支持嵌套子命令,使得开发者可以轻松构建复杂的命令行工具。
- 与 Click 的兼容性:Typer 基于 Click 构建,因此完全兼容 Click 的功能,同时提供了更现代化的开发体验。
优势
- 开发效率高:Typer 的简洁 API 和自动生成帮助文档的功能显著提升了开发效率。
- 代码可读性强:基于类型提示的代码更加清晰和易于理解。
- 类型安全:Typer 的类型检查功能可以在开发阶段捕捉到潜在的错误,减少运行时问题。
首先创建一个虚拟环境:
$ uv venv --pythnotallow=3.11.10
Using CPython 3.11.10
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
然后使用 uv init 从头开始创建一个新项目:
$ uv init --name demo --python 3.11.10 --package
Initialized project `demo`
这样就创建了一个项目:
$ tree
.
├── pyproject.toml
├── README.md
└── src
└── demo
└── __init__.py
然后,我们可以使用 uv add 将 typer 添加为依赖关系:
$ uv add typer
Using CPython 3.11.10
Creating virtual environment at: .venv
Resolved 10 packages in 2ms
Installed 8 packages in 9ms
+ click==8.1.8
+ markdown-it-py==3.0.0
+ mdurl==0.1.2
+ pygments==2.18.0
+ rich==13.9.4
+ shellingham==1.5.4
+ typer==0.15.1
+ typing-extensinotallow==4.12.2
然后,我们添加修改 Python 文件 src/demo/__init__.py,使其包含一个简单的 CLI:
import typer
app = typer.Typer()
@app.command()
def main(name: str) -> None:
print(f"Hello {name}")
我们需要将此添加到 pyproject.toml 中,以便使用 demo 命令运行 CLI:
demo = "demo:app"
这是完整的 pyproject.toml:
[project]
name = "demo"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
authors = [
{ name = "Adam Green", email = "adam.green@adgefficiency.com" }
]
requires-python = ">=3.11.10"
dependencies = [
"typer>=0.15.1",
]
[project.scripts]
demo = "demo:app"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
由于我们在 pyproject.toml 中包含了 [project.scripts],因此可以使用 uv run 运行此 CLI:
$ uv run demo omega
Hello omega
Typer 为我们免费提供了“--help ”标志:
$ python src/demo/__init__.py --help
Usage: demo [OPTIONS] NAME
╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
│ * name TEXT [default: None] [required] │
╰──────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
│ --install-completion Install completion for the current shell. │
│ --show-completion Show completion for the current shell, to copy it or customize │
│ the installation. │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────╯
Tips: 你可以在 Typer 中使用命令和命令组创建嵌套的 CLI 组。
Rich
Rich[5] 是一个功能强大的 Python 库,专门用于在终端中输出美观、格式化的文本内容。它通过丰富的样式、颜色、表格、进度条等功能,彻底改变了传统 Python 程序单调乏味的终端输出方式,为开发者提供了一种更加直观和优雅的展示方式。无论是调试信息、日志记录,还是数据展示,Rich 都能让你的终端输出焕然一新。
图片
核心功能
- 丰富的文本样式:Rich 支持多种文本样式,包括颜色、粗体、斜体、下划线、背景色等。开发者可以轻松地为终端输出添加视觉层次,使其更具可读性和吸引力。
- 表格输出:Rich 提供了强大的表格功能,支持自动调整列宽、对齐方式、边框样式等。无论是展示数据还是生成报告,Rich 的表格功能都能让信息更加清晰和结构化。
- 进度条:Rich 内置了多种进度条样式,支持实时更新和多任务进度跟踪。这对于长时间运行的任务(如数据处理、文件下载等)非常有用,能够直观地展示任务进度。
- 语法高亮:Rich 支持代码片段的语法高亮,能够自动识别多种编程语言(如 Python、JSON、Markdown 等),并在终端中以彩色形式展示代码。
- Markdown 渲染:Rich 可以直接在终端中渲染 Markdown 文档,支持标题、列表、代码块、链接等 Markdown 语法,使得文档展示更加美观。
- 日志格式化:Rich 提供了高度可定制的日志格式化功能,开发者可以为日志添加颜色、时间戳、调用栈信息等,使得日志记录更加直观和易于分析。
优势
- 提升可读性:Rich 的丰富样式和颜色使得终端输出更加直观和易于理解。
- 简化开发:Rich 提供了简单易用的 API,开发者只需几行代码即可实现复杂的终端输出效果。
- 高度可定制:Rich 支持多种自定义选项,开发者可以根据需求调整输出样式和格式。
- 跨平台支持:Rich 在 Windows、macOS 和 Linux 上都能完美运行,确保开发者可以在不同平台上获得一致的体验。
Rich 的特点是打印出漂亮的颜色和表情符号:
import rich
user = {'name': 'omega', 'id': 'invalid'}
print(f" normal printing\nuser {user}\n")
rich.print(f" :wave: rich printing\nuser {user}\n")
normal printing
user {'name': 'omega', 'id': 'invalid'}
👋 rich printing
user {'name': 'omega', 'id': 'invalid'}
Features
如果你对 Rich 感兴趣,可以用 Rich 打印代替内置打印,从而简化代码:
from rich.console import Console
from rich.table import Table
from rich.progress import track
import time
# 创建 Console 对象
console = Console()
# 输出彩色文本
console.print("[bold red]Hello, [green]Rich[/green]![/bold red]")
# 创建表格
table = Table(title="示例表格")
table.add_column("ID", justify="right", style="cyan")
table.add_column("名称", style="magenta")
table.add_column("描述", style="green")
table.add_row("1", "Python", "一种流行的编程语言")
table.add_row("2", "Rich", "一个终端美化工具")
console.print(table)
# 进度条示例
for i in track(range(10), descriptinotallow="处理中..."):
time.sleep(0.5)
此外,Rich 有一个检查功能,可以对任何 Python 对象(例如类、实例或内置对象)生成报告。
my_list = ["foo", "bar"]
from rich import inspect
inspect(my_list, methods=True)
日志
Tips: Rich 提供了比颜色和表情符号更多的功能,包括显示表格数据和更好的 Python 错误回溯。
写在最后
最后我们对本次分享做个总结:
uv 是一个现代化的 Python 版本管理工具,通过其自动化、高效和跨平台的特点,帮助开发者更轻松地管理复杂的 Python 开发环境。无论是个人开发者还是团队,uv 都能显著提升开发效率和环境配置的便捷性。
Ruff 是一个集速度、功能和易用性于一体的 Python 代码工具,适合希望提升代码质量和开发效率的开发者。无论是个人项目还是团队协作,Ruff 都能成为你的得力助手,帮助你更轻松地编写高质量的 Python 代码。
mypy 作为 Python 静态类型检查的领先工具,正在帮助开发者构建更可靠、更易维护的代码。随着 Python 社区对静态类型的接受度不断提高,mypy 将成为现代 Python 开发中不可或缺的一部分。
Typer 是一个现代化的 Python CLI 开发工具,通过其简洁的 API 和强大的类型提示功能,帮助开发者快速构建高效、易维护的命令行应用程序。结合 uv 的环境管理能力,开发者可以更轻松地配置和部署 Python 项目。无论是个人项目还是团队工具,Typer 都能显著提升开发效率和代码质量。
Rich 是一个现代化的 Python 终端美化工具,通过其丰富的功能和简洁的 API,帮助开发者以更美观、更直观的方式展示终端输出。无论是调试信息、数据展示,还是日志记录,Rich 都能显著提升终端输出的质量和用户体验。如果你厌倦了单调的终端输出,Rich 无疑是你的理想选择。
参考资料
[1]uv: https://docs.astral.sh/uv/
[2]Ruff: https://docs.astral.sh/ruff/
[3]mypy: http://www.mypy-lang.org/
[4]Typer: https://typer.tiangolo.com/
[5]Rich: https://rich.readthedocs.io/en/stable/