Python
参考资料
工具
Python Install Manager
- Windows 上官方推荐从 python.org 或 Microsoft Store 安装 Python Install Manager
py # 启动默认 Python
py -V:3.14 # 指定运行 Python 3.14
py list # 查看已安装运行时
py list --online # 查看可安装运行时
py install 3.14 # 安装指定版本
py install --update # 更新由 install manager 管理的运行时
py uninstall 3.13 # 卸载指定版本
py -m pip --version # 用指定解释器运行模块
venv 与 pip
venv 是标准库模块, 用来创建轻量虚拟环境
pip 是包安装器, 最稳的调用方式是 python -m pip, 这样能确保操作的是当前解释器
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -U pip
python -m pip install rich
python -m pip freeze > requirements.txt
deactivate
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install rich
python -m pip freeze > requirements.txt
deactivate
uv
安装
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv --version
curl -LsSf https://astral.sh/uv/install.sh | sh
uv --version
项目管理
uv init demo # 创建项目
cd demo
uv python pin 3.14 # 固定项目 Python 版本
uv add rich # 写入依赖并同步环境
uv add --dev pytest ruff pyright # 写入开发依赖
uv run python -m demo
uv run pytest
uv lock # 生成 uv.lock
uv sync # 按锁文件重建环境
uv remove rich # 删除依赖
uv tree # 查看依赖树
Python 版本管理
uv python list
uv python install 3.12 3.13 3.14
uv python pin 3.14
uv venv --python 3.14
uv run --python 3.14 python -V
uv run --python pypy@3.10 python -V
工具机制
uvx ruff check .
uv tool run black --check .
uv tool install ruff
uv tool install pyright
uv tool list
uv tool uninstall ruff
pip 兼容层
uv venv
uv pip install -r requirements.txt
uv pip compile requirements.in -o requirements.txt
uv pip sync requirements.txt
构建与发布
Conda 家族
- Anaconda: 大而全, 适合教学和开箱即用, 但默认安装体积大
- Miniconda: Anaconda 官方的最小 conda 安装器, 只带 conda, Python 和少量基础包
- Miniforge3: conda-forge 社区的最小安装器
- Mamba: conda 环境管理 CLI, 命令大多和 conda 接近, 解析速度通常更快
conda 是命令, conda-forge 是包源, 当前默认源可以用 conda config --show channels 看
conda create -n py314 python=3.14
conda activate py314
conda install -c conda-forge rich # 指定源安装
conda env export > environment.yml # 导出环境
conda env list
conda deactivate
conda env remove -n py314
name: demo
channels:
- conda-forge
dependencies:
- python=3.14
- rich
- pip
- pip:
- typer
Pixi
- Pixi 是基于 conda-forge / prefix.dev 生态的项目环境工具
- 相比 conda, Pixi 更项目化, 相比 uv, Pixi 更擅长非 Python 依赖和多语言依赖
powershell -ExecutionPolicy ByPass -c "irm -useb https://pixi.sh/install.ps1 | iex"
pixi --version
pixi init demo
cd demo
pixi add python rich
pixi task add start "python -c \"import rich, print('ok')\"" # 添加任务
pixi run start # 运行任务
pixi shell # 进入环境
pixi global install ripgrep fd # 安装全局命令
常用工具
- Ruff: lint, format, import 排序和一部分自动修复
- Pyright: 静态类型检查器
- pre-commit: 管 Git hook
- nox: 跑测试矩阵, 比如同一套测试在 Python 3.12/3.13/3.14 上都跑一遍
- httpie: 命令行 HTTP 客户端
- pip-audit: 检查依赖里有没有已知安全漏洞
- py-spy: Python 采样分析器
- direnv: 进目录自动加载环境变量, 比如自动设置
VIRTUAL_ENV, API key, 私有源地址
模块, 包与打包
模块与包
模块
- 一个
.py 文件就是一个模块, 文件名就是模块名
- 模块可以被
import 导入, 也可以作为脚本直接运行
if __name__ == "__main__": 用来区分当前文件是被导入, 还是被直接运行
- 不要把文件命名为
json.py, typing.py, requests.py 这类容易遮蔽标准库或三方库的名字
包
- 一个目录包含
__init__.py 时就是常规包
__init__.py 的作用:
- 导入包时会先执行它, 比如
import package 会执行 package/__init__.py
- 可以在里面整理包的对外 API, 比如
from .core import Client, 让用户可以写 from package import Client
- 可以定义
__all__, __version__ 等包级别信息
- 没有
__init__.py 的目录也可能作为 namespace package 工作
- namespace package 的意思是: 同一个顶层导入包名可以分散在多个安装位置里
- 常见场景是多个发行包共同贡献同一个顶层包名
- 比如
pip install acme-core 提供 acme/core.py, pip install acme-auth 提供 acme/auth.py, 它们都挂在同一个 acme 顶层包下面
- 用户使用时可以分别导入
import acme.core 和 import acme.auth
运行与导入规则
sys.path 决定 Python 从哪里找模块和包, 通常包括脚本目录, 环境变量 PYTHONPATH, 标准库和 site-packages
- shell 当前目录主要影响两件事: Python 从哪里找顶层包, 以及
open("file.txt") 这种普通相对文件路径
python -m package.module 会先从 sys.path 中找到 package, 再把 module 当作包内模块执行
- 显式相对导入, 如
from . import sibling, 不是按 shell 当前目录算, 而是按 __package__ 这个包上下文算
- 直接运行
python package/module.py 时, 这个文件常常只被当作普通脚本, __package__ 为空, from . import sibling 就容易失败
src 布局
src 布局能避免测试时误导入项目根目录里的源码, 更接近真实安装后的状态
- distribution package 是发布到 PyPI 的包名, import package 是
import 的模块名, 两者可以不同
pip install beautifulsoup4
from bs4 import BeautifulSoup
pyproject.toml
# 声明构建后端和构建依赖
[build-system]
requires = ["hatchling >= 1.26"]
build-backend = "hatchling.build"
# 声明标准项目元数据
[project]
name = "demo-pkg"
version = "0.1.0"
description = "A small Python package"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"rich>=13",
]
# 声明用户可安装的 extra
[project.optional-dependencies]
cli = ["typer>=0.12"]
# 声明开发依赖组, 不会进入构建后的包元数据
[dependency-groups]
dev = ["pytest>=8", "ruff>=0.5", "pyright>=1.1"]
# 声明可执行脚本, 让用户安装后能直接在 shell 里运行
[project.scripts]
demo = "demo_pkg.cli:main"
# 声明工具配置
[tool.ruff]
line-length = 100
- build backend 常见选择:
- Hatchling: 新项目友好, 纯 Python 包很顺
- Setuptools: 兼容最广, 历史项目和 C 扩展常见
- Flit: 简洁发布纯 Python 库
- PDM backend: PDM 生态
uv_build: uv 生态的新构建后端
构建一个包
python -m pip install -U build twine
python -m build
twine check dist/*
twine upload dist/*
python -m build 通常产出两个文件:
- sdist:
dist/name-version.tar.gz, 源码分发包
- wheel:
dist/name-version-py3-none-any.whl, 构建分发包, 安装更快
- 库项目的
dependencies 不要锁死全部间接依赖, 否则会让使用者无法组合
标准库
诊断
inspect: 运行时观测函数, 类, 签名, 源码
traceback: 异常堆栈
warnings: 发出不中断程序的警告, 常用于库的兼容提示
tracemalloc: 跟踪内存分配
logging: 日志系统
性能
cProfile -> pstats: 性能分析 -> 展示, 找程序慢在哪里
timeit: 给小段代码计时, 做微基准测试
time: 时间戳, 睡眠, 性能计时, 重点知道 perf_counter()
功能
pickle: Python 对象序列化, 只反序列化可信数据 (因为本质是按指令重建对象)
importlib: 动态导入模块
pkgutil: 包发现和模块遍历, 常见于插件系统
decimal: 十进制定点数, 适合金额等不能接受二进制浮点误差的场景
copy: 浅拷贝和深拷贝, 重点知道 copy.deepcopy()
sqlite3: 嵌入式 SQLite 数据库
类型
typing: 类型标注
collections: 增强容器
types: 运行时创建类型
itertools: 惰性迭代工具, 被调用时生成
functools: 函数工具, 主要是一堆装饰器和高阶函数, 比如 lru_cache, partial, wraps
dataclasses: 数据类, 自动生成 __init__, repr, eq
enum: 枚举
常用三方库
- tqdm: 进度条
- python-dotenv: 从
.env 加载环境变量
- PyInstaller: 把 Python 应用打包成单目录或单文件可执行程序
- pytest: 测试框架
并发与并行
- 并发: 生命周期重叠
- 并行: 同时执行
- 任务: 要做的一段工作
- 执行单元: 维护任务状态和调度的东西, 比如线程, 协程, 进程
- 调度器: 决定现在推进谁, 比如协程的 event loop
- 等待点: 当前任务主动或被动停下来的地方, 协程
await, 线程不可控
GIL
- GIL 是 CPython 的全局解释器锁
- GIL 不阻止线程并发等待 I/O, 因为阻塞 I/O 和很多 C 扩展会释放 GIL
- 多进程可以绕过 GIL, 因为每个进程有自己的解释器和自己的 GIL
- Python 3.14 的
InterpreterPoolExecutor 使用多个子解释器, 每个解释器有自己的 GIL
- CPython 3.13 开始提供 free-threaded 构建作为关闭 GIL 的实验方向
- 本质是为了保护 Python 中的对象 (引用计数 / 内部结构)
- 解决办法是对象乐观锁 + 偏向引用计数
- 部分 C 拓展需要适配一下
asyncio
async def coro():
await asyncio.sleep(1)
return
async def fun1():
result1 = await coro()
result2 = await coro() # 顺序等待, 不是并发, 2s
async def fun2():
task1 = asyncio.create_task(coro())
task2 = asyncio.create_task(coro()) # 创建两个 task, 塞进 event loop
result1 = await task1
result2 = await task2 # 并发等待, 大约 1s
Future 是代替回调的机制, 创建一个 Future 对象, 让它在某个时刻被设置结果, 其他协程可以 await 它
asyncio API
Task.cancel(): 取消任务, 让它在下一个等待点抛 CancelledError
finally 块仍然会执行, 可以在里面做清理
- 如果捕获
CancelledError, 务必 raise
- 事件循环
asyncio.run(coro): 创建 event loop, 跑入口协程, 结束后关闭 loop
asyncio.create_task(coro): 把协程包装成 Task, 让它开始被 event loop 调度
- 并发控制
asyncio.TaskGroup: 结构化并发, 一组任务作为一个生命周期单元
3.11 引入, 失败请求取消全部任务, 并把异常聚合成 ExceptionGroup
asyncio.gather(): 并发等待多个子任务, 通常按输入顺序返回结果
- 一个失败, 其它不会自动取消
return_exceptions=True 能把异常当结果返回
asyncio.wait(): 等一批任务达到某个条件, 返回 done 和 pending 两组
- 设定条件是超时, 不会自动取消任务
asyncio.wait_for() 可以指定超时取消
asyncio.as_completed(): 谁先完成就先处理谁
asyncio.sleep(): 非阻塞睡眠, 让 event loop 去跑别的任务
- 工具
asyncio.Queue: 协程之间传消息, put() 放入, get() 取出, task_done() 标记完成, join() 等所有任务完成
- 卸载
asyncio.to_thread(): 在默认线程池中跑同步阻塞函数, 避免卡住 event loop
loop.run_in_executor(): 指定线程池或进程池执行同步函数
asyncio.create_subprocess_exec(): 异步启动和等待子进程
threading
import threading
def worker(name: str) -> None:
print("开始:", name)
thread = threading.Thread(
target=worker,
args=("worker-1",),
)
thread.start()
thread.join() # 等待线程结束
threading API
Lock: 互斥锁, 同一时间只允许一个线程进入临界区
RLock: 可重入锁, 同一线程可以重复获得同一把锁
Condition: 条件变量
Semaphore: 计数信号量
BoundedSemaphore: 带上界检查的信号量, 多释放会报错
Event: 一个布尔信号, set() 后唤醒等待者
Barrier: 等固定数量线程都到达某点后一起继续
Timer: 延迟一段时间后在线程里执行函数
local: 线程本地存储, 每个线程看到自己的值
current_thread(): 当前线程对象
get_ident(): 当前线程的 Python 线程标识
get_native_id(): 当前线程的系统线程 ID
queue
concurrent.futures
- Executor 管一组 worker
submit(fn, *args) 把函数交给 worker 执行
- 立刻返回
Future
- 主线程可以
result() 等结果, cancel() 取消未开始的任务, as_completed() 谁先结束就处理谁
API 先解释
Executor.submit(): 提交一个函数调用, 返回 Future
Executor.shutdown(): 关闭池, with 会自动调用
Future.result(): 等任务完成并返回结果, 任务抛异常则这里重新抛
Future.exception(): 取任务异常
Future.cancel(): 尝试取消还没开始的任务
Future.done(): 是否结束
Future.running(): 是否正在运行
Future.add_done_callback(): 完成时回调
ThreadPoolExecutor: 线程池
ProcessPoolExecutor: 进程池
InterpreterPoolExecutor: Python 3.14+ 解释器池, 隔离性强于线程, 通信成本类似序列化
multiprocessing
- 独立的进程, 每个进程有自己的 Python 解释器和 GIL, 可以多核并行
- 参数和结果通常通过 pickle 序列化
multiprocessing.shared_memory: 共享大块原始内存
contextvars 异步上下文隔离
threading.local() 是按线程隔离
ContextVar 是按逻辑上下文隔离
contextvars API
ContextVar(name, default=...): 定义一个上下文变量, 应放在模块顶层
get(): 读取当前 context 中的值
set(value): 设置当前 context 的值, 返回 token
reset(token): 恢复到 set 之前的值
copy_context(): 复制当前 context, 可手动在这个 context 里运行函数
Token: set() 返回的恢复凭据, Python 3.14+ 也支持作为 context manager 使用
subprocess 外部子进程
concurrent.interpreters 同进程多解释器
- 每个解释器有自己的模块导入状态
- 每个解释器有自己的全局变量和
sys, builtins, __main__
- 每个解释器有自己的 GIL
- 多个解释器之间不能随便共享可变 Python 对象
- 传参数和返回结果通常需要复制或 pickle