跳转至

Python 完整指南

适用人群:希望用 Python 编写脚本、数据处理程序、Web 服务或 AI 应用的学习者
前置要求:会使用终端,理解文件、目录和程序的基本概念
最后更新:2026-07-21

Python 的优势不在某一个语法特性,而在于它用较低的表达成本连接了自动化、Web、数据科学和人工智能生态。本章不尝试罗列语言的每个角落,而是建立一条可直接工作的主线:先获得可重复的运行环境,再掌握常用数据结构和控制流,随后学习文件、异常、模块、测试与项目组织,最后用速查表完成日常查询。

1. 先理解 Python 程序如何运行

Python 源文件通常以 .py 结尾。执行 python app.py 时,解释器读取源码、编译为字节码,再由 Python 虚拟机执行。日常所说的“Python 版本”通常指 CPython 解释器版本。Python 2 已停止维护,新项目只使用仍受支持的 Python 3。

python3 --version
python3 -c 'import sys; print(sys.executable); print(sys.version)'

sys.executable 能回答“当前到底使用了哪一个 Python”,比只看命令提示符可靠。macOS 和 Linux 上通常使用 python3,进入虚拟环境后使用 python;Windows 可以使用 python 或 Python Launcher 的 py

Python 适合快速开发和生态集成,但不是所有场景的默认答案。CPU 密集型底层系统、硬实时任务或极端低延迟组件可能更适合 Rust、C++、Go 等语言;Python 常通过 NumPy、PyTorch 等由底层编译代码实现的库获得计算性能。

安装与验证

优先从 Python 官方下载页 或操作系统包管理器安装。不要修改系统组件依赖的 Python,也不要把第三方包直接安装到系统环境。

# macOS
brew install python

# Ubuntu/Debian:发行版仓库版本最稳定
sudo apt update
sudo apt install python3 python3-venv python3-pip

# Windows PowerShell:先查看当前稳定版本对应的包 ID
winget search --id Python.Python

安装后进行最小验证:

python3 --version
python3 -m pip --version
python3 -c 'print("Python is ready")'

需要同时维护多个 Python 版本时再引入 pyenvuv;科学计算环境依赖复杂的本地库时可使用 Conda。初学阶段只掌握“一个项目、一个虚拟环境”即可,过早混用多个环境管理器反而增加路径问题。

2. 虚拟环境和依赖:每个项目都要隔离

两个项目可能分别依赖同一库的不同版本。虚拟环境为项目创建独立解释器入口和包目录,使升级 A 项目不会破坏 B 项目。标准流程如下:

mkdir demo-python && cd demo-python
python3 -m venv .venv

# macOS / Linux
source .venv/bin/activate

# Windows PowerShell
.venv\Scripts\Activate.ps1

python -m pip install --upgrade pip
python -m pip install requests
python -c 'import requests; print(requests.__version__)'
deactivate

始终使用 python -m pip,它明确调用当前解释器对应的 pip,避免 pythonpip 来自不同环境。.venv/ 是可重建目录,必须加入 .gitignore,不能提交到仓库。

.venv/
__pycache__/
*.py[cod]
.pytest_cache/
.ruff_cache/
.env

requirements.txt 与 pyproject.toml

简单脚本可以使用 requirements.txt

requests>=2.32,<3
python -m pip install -r requirements.txt
python -m pip list
python -m pip show requests
python -m pip check

可安装项目、库和长期维护的应用应使用 pyproject.toml 描述项目元数据和直接依赖:

[build-system]
requires = ["setuptools>=75"]
build-backend = "setuptools.build_meta"

[project]
name = "log-summary"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["requests>=2.32,<3"]

[project.optional-dependencies]
dev = ["pytest>=8", "ruff>=0.9"]

[project.scripts]
log-summary = "log_summary.cli:main"
python -m pip install -e '.[dev]'

-e 表示 editable install,修改本地源码后无需重复安装。应用部署还需要锁定经过测试的间接依赖版本,可以使用组织选定的锁文件工具;不要把 pip freeze 得到的整台机器快照当作库的依赖声明。

3. 变量、对象与基本类型

Python 变量保存对象引用,不需要预先声明类型。赋值不会复制对象:

count = 3                  # int
ratio = 0.75               # float
enabled = True             # bool
name = "python"            # str
missing = None             # NoneType

items = ["a", "b"]
alias = items
alias.append("c")
print(items)               # ['a', 'b', 'c']

判断空值使用 is None,比较值使用 ==

if missing is None:
    print("no value")

if name == "python":
    print("same text")

整数没有固定精度上限;浮点数遵循二进制浮点规则,不能精确表示所有十进制小数。金额等需要十进制精确计算的场景使用 decimal.Decimal

from decimal import Decimal

total = Decimal("0.10") + Decimal("0.20")
print(total)               # 0.30

字符串与格式化

字符串是不可变 Unicode 序列。最常用操作包括切片、拆分、清理和拼接:

text = "  Alice,admin  "
clean = text.strip()
user, role = clean.split(",", maxsplit=1)

print(user.lower())
print(role.upper())
print(f"user={user!r}, role={role!r}")

常见格式:

value = 12.3456
print(f"{value:.2f}")       # 12.35
print(f"{1024 * 1024:,}")  # 1,048,576

文本与字节必须明确区分。网络和文件底层传输 bytes,业务文本通常使用 str

payload = "你好".encode("utf-8")
text = payload.decode("utf-8")

4. 四种核心容器类型

选择数据结构时先问是否需要顺序、修改、唯一性和键值查询。

类型 特征 常用场景
list 有序、可变、允许重复 一组按顺序处理的对象
tuple 有序、不可变 固定记录、函数返回多个值
set 无重复、支持集合运算 去重、成员测试
dict 键到值的映射 配置、索引、结构化记录
names = ["alice", "bob", "alice"]
names.append("carol")
first_two = names[:2]

point = (10, 20)
x, y = point

unique_names = set(names)
is_known = "alice" in unique_names

user = {"name": "alice", "role": "admin"}
role = user.get("role", "viewer")
for key, value in user.items():
    print(key, value)

复制可变容器时要注意浅复制只复制外层:

from copy import deepcopy

original = {"tags": ["a", "b"]}
shallow = original.copy()
complete = deepcopy(original)

推导式适合简短的映射和过滤,但复杂逻辑应改用普通循环:

squares = [n * n for n in range(10) if n % 2 == 0]
by_name = {item["name"]: item for item in records}

5. 条件、循环与模式匹配

Python 使用缩进表达代码块,标准缩进是四个空格。空字符串、空容器、数字零和 None 在条件中视为假。

if status == 200:
    result = "ok"
elif 400 <= status < 500:
    result = "client error"
else:
    result = "other"

遍历时优先使用迭代协议,不要手工维护下标:

for index, name in enumerate(names, start=1):
    print(index, name)

for name, score in zip(names, scores, strict=True):
    print(name, score)

for attempt in range(3):
    if connect():
        break
else:
    raise RuntimeError("all attempts failed")

break 结束当前循环,continue 跳过本轮,while 适合循环次数取决于运行状态的场景。所有 while 都应有可理解的结束条件。

Python 3.10 以后可用 match 处理结构化分支:

match event:
    case {"type": "created", "id": item_id}:
        handle_created(item_id)
    case {"type": "deleted", "id": item_id}:
        handle_deleted(item_id)
    case _:
        raise ValueError("unsupported event")

6. 函数:明确输入、输出和副作用

函数应完成一个清晰动作。参数和返回值使用类型注解,文档说明业务含义和异常,而不是逐行复述代码。

def calculate_total(
    prices: list[float],
    *,
    discount: float = 0.0,
) -> float:
    """Return the discounted total; raise on an invalid discount."""
    if not 0 <= discount <= 1:
        raise ValueError("discount must be between 0 and 1")
    return sum(prices) * (1 - discount)


total = calculate_total([10.0, 20.0], discount=0.1)

* 之后的参数必须按名称传入,能减少布尔值和数字参数位置混淆。默认值应使用不可变对象:

def add_tag(tag: str, tags: list[str] | None = None) -> list[str]:
    result = [] if tags is None else list(tags)
    result.append(tag)
    return result

不要写 tags=[],因为默认列表只创建一次,会在调用之间共享。

*args 收集额外位置参数,**kwargs 收集额外关键字参数。它们适合适配器和装饰器,不应替代明确的业务参数。

def log_event(event: str, **fields: object) -> None:
    print(event, fields)

7. 模块、包与项目结构

每个 .py 文件是模块,包含 __init__.py 的目录通常作为包。推荐使用 src 布局,避免测试时意外导入工作目录中的源码:

log-summary/
├── pyproject.toml
├── README.md
├── src/
│   └── log_summary/
│       ├── __init__.py
│       ├── cli.py
│       └── parser.py
└── tests/
    └── test_parser.py
# src/log_summary/cli.py
from log_summary.parser import summarize


def main() -> None:
    print(summarize("events.log"))


if __name__ == "__main__":
    main()

导入顺序通常是标准库、第三方包、本项目模块。避免 from module import *,它会隐藏名称来源并增加冲突。

循环导入通常说明模块职责互相依赖。可通过抽取共享类型、移动导入到共同底层模块或重新划分边界解决,不要默认用函数内导入掩盖设计问题。

8. 文件、路径、JSON 与 CSV

路径操作优先使用 pathlib,文件读写明确编码,并用 with 保证资源关闭:

from pathlib import Path

path = Path("data") / "message.txt"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("hello\n", encoding="utf-8")

for line in path.read_text(encoding="utf-8").splitlines():
    print(line)

大文件不要一次 read_text() 全部加载,应流式迭代:

with path.open(encoding="utf-8") as file:
    for line_number, line in enumerate(file, start=1):
        process(line_number, line.rstrip("\n"))

JSON 只支持有限类型,日期、自定义对象和集合需要转换:

import json
from pathlib import Path

data = {"name": "alice", "roles": ["admin"]}
Path("user.json").write_text(
    json.dumps(data, ensure_ascii=False, indent=2),
    encoding="utf-8",
)

loaded = json.loads(Path("user.json").read_text(encoding="utf-8"))

CSV 使用标准库时应指定 newline=""

import csv

with open("users.csv", newline="", encoding="utf-8") as file:
    for row in csv.DictReader(file):
        print(row["name"])

临时文件使用 tempfile,文件复制使用 shutil,不要用字符串拼接路径或调用 shell 的 cp 完成跨平台文件操作。

9. 异常、日志与资源清理

异常表示当前层无法正常完成操作。捕获范围应尽量小,并捕获可以处理的具体异常:

import json
from pathlib import Path


def load_config(path: Path) -> dict[str, object]:
    try:
        text = path.read_text(encoding="utf-8")
        return json.loads(text)
    except FileNotFoundError as exc:
        raise RuntimeError(f"config not found: {path}") from exc
    except json.JSONDecodeError as exc:
        raise RuntimeError(
            f"invalid JSON at line {exc.lineno}, column {exc.colno}"
        ) from exc

不要使用空的 except:,也不要捕获后什么都不做。raise ... from exc 保留原始错误链。finally 适合必须执行的清理,但文件、锁和连接更推荐使用上下文管理器。

生产程序使用 logging 而不是散落的 print

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger(__name__)

logger.info("processing started", extra={"job_id": "job-42"})

日志应包含时间、级别、组件和用于关联请求的 ID,但不能记录密码、令牌和完整个人敏感信息。

10. 类、dataclass 与类型注解

简单数据记录优先使用 dataclass,只有对象确实需要维护状态和行为时才创建复杂类。

from dataclasses import dataclass


@dataclass(frozen=True, slots=True)
class User:
    name: str
    roles: tuple[str, ...]

    def can(self, role: str) -> bool:
        return role in self.roles

frozen=True 表达不可变意图,slots=True 限制随意增加属性。继承适合真正的“是一个”关系,复用行为时通常优先组合。

类型注解不会在运行时自动验证输入,但能让编辑器和静态检查器提前发现问题:

from collections.abc import Iterable


def average(values: Iterable[float]) -> float:
    items = list(values)
    if not items:
        raise ValueError("values cannot be empty")
    return sum(items) / len(items)

对外部 JSON、表单和环境变量仍需运行时校验。类型注解描述程序内部约定,不能替代边界验证。

11. 迭代器、生成器与上下文管理器

可迭代对象能产生迭代器,迭代器逐个返回值。生成器用 yield 按需计算,适合大数据流:

from collections.abc import Iterator
from pathlib import Path


def error_lines(path: Path) -> Iterator[str]:
    with path.open(encoding="utf-8") as file:
        for line in file:
            if "ERROR" in line:
                yield line.rstrip("\n")

生成器是一次性数据流,消费后不能自动重放。需要重复遍历时重新创建生成器或显式转为列表。

上下文管理器负责成对的获取与释放。除文件外,数据库事务、锁和临时目录都应采用 with

from contextlib import contextmanager
from time import perf_counter


@contextmanager
def timer(name: str):
    start = perf_counter()
    try:
        yield
    finally:
        print(f"{name}: {perf_counter() - start:.3f}s")

12. 并发、并行与 async

三种常见需求要分开:等待网络或磁盘属于 I/O 密集;大量 Python 计算属于 CPU 密集;同时服务大量连接适合异步 I/O。

需求 常用工具 说明
少量阻塞 I/O 并发 ThreadPoolExecutor 线程共享内存,注意线程安全
CPU 密集并行 ProcessPoolExecutor 多进程有序列化和启动成本
大量异步连接 asyncio 依赖库也必须支持异步
from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor(max_workers=8) as pool:
    results = list(pool.map(fetch_url, urls))
import asyncio


async def main() -> None:
    results = await asyncio.gather(fetch_a(), fetch_b())
    print(results)


asyncio.run(main())

不要在 async def 中直接调用耗时的同步网络或文件函数,它会阻塞事件循环。并发还需要超时、取消、连接池和并发上限,不能只追求同时启动更多任务。

13. 测试、调试和代码质量

测试描述程序在给定输入下必须保持的行为。使用 pytest 时,测试文件和函数通常以 test_ 开头:

# src/log_summary/parser.py
def parse_level(line: str) -> str:
    if not line.strip():
        raise ValueError("empty line")
    return line.split(maxsplit=1)[0]
# tests/test_parser.py
import pytest

from log_summary.parser import parse_level


@pytest.mark.parametrize(
    ("line", "expected"),
    [("INFO started", "INFO"), ("ERROR failed", "ERROR")],
)
def test_parse_level(line: str, expected: str) -> None:
    assert parse_level(line) == expected


def test_parse_level_rejects_empty_line() -> None:
    with pytest.raises(ValueError, match="empty"):
        parse_level("  ")
pytest -q
pytest -q tests/test_parser.py
pytest -q -k parse_level

遇到问题先保留完整 traceback。最下方通常是直接异常,上方是调用链。可用 breakpoint() 暂停并检查变量:

def calculate(value: int) -> int:
    breakpoint()
    return value * 2

日常质量工具可以收敛为 Ruff 与 pytest:

python -m pip install ruff pytest
ruff check .
ruff format --check .
pytest -q

格式化解决排版一致性,lint 检查常见错误,类型检查验证静态约定,测试验证行为;它们不能互相替代。

14. 配置、环境变量与命令行程序

配置应与代码分离。环境变量输入始终是字符串,需要显式转换和验证:

import os


def read_port() -> int:
    value = int(os.getenv("APP_PORT", "8000"))
    if not 1 <= value <= 65535:
        raise ValueError("APP_PORT must be between 1 and 65535")
    return value

秘密不要写进源码、Dockerfile、命令示例或 Git。.env 只适合本地开发且必须忽略,生产环境使用平台秘密管理服务。

标准库 argparse 足以编写稳定 CLI:

import argparse


def main() -> None:
    parser = argparse.ArgumentParser(description="Summarize a log file")
    parser.add_argument("path")
    parser.add_argument("--level", default="ERROR")
    args = parser.parse_args()
    print(args.path, args.level)


if __name__ == "__main__":
    main()
python -m log_summary.cli --help
python -m log_summary.cli app.log --level WARNING

15. 常见问题的定位顺序

python: command not found

先确认平台命令名和路径:

command -v python3
python3 --version

Windows 使用 where pythonpy -0p。不要通过随意修改系统软链接解决版本问题。

包已经安装却 ModuleNotFoundError

多数情况是安装包和运行程序使用了不同解释器:

python -c 'import sys; print(sys.executable)'
python -m pip --version
python -m pip show PACKAGE_NAME

确认虚拟环境已激活,并检查模块名是否与安装包名不同、当前目录是否存在同名文件遮蔽第三方包。

依赖冲突

python -m pip check
python -m pip list --outdated

在全新的虚拟环境中根据依赖文件重建,比在污染环境里反复升级降级更可靠。不要同时让 Conda 和 pip 管理同一个底层二进制依赖,除非理解两者边界。

编码错误

文件读写明确写 encoding="utf-8"。无法解码时先确认真实编码,不要用 errors="ignore" 静默丢失数据。

程序很慢或占用内存过大

先测量再优化。使用生成器避免一次加载全部数据;减少循环中的重复 I/O;对 CPU 瓶颈使用 profiler;数据计算优先使用向量化库。不要因为 Python 循环慢就盲目增加线程。

16. 高频语法与命令速查

环境与依赖

目的 命令
查看解释器 python -c 'import sys; print(sys.executable)'
创建环境 python3 -m venv .venv
激活环境 source .venv/bin/activate
安装依赖 python -m pip install PACKAGE
从文件安装 python -m pip install -r requirements.txt
查看包 python -m pip show PACKAGE
检查冲突 python -m pip check
安装当前项目 python -m pip install -e '.[dev]'

常用内置函数

函数 用途
len(x) 元素数量
type(x) / isinstance(x, T) 类型检查
range() 整数序列
enumerate() 同时获取索引和值
zip() 并行遍历多个序列
sorted() 返回排序后的新列表
sum() / min() / max() 聚合数值
any() / all() 任一或全部条件判断
open() 打开文件,通常配合 with

高频标准库

模块 主要用途
pathlib 路径和文件操作
json / csv 数据交换格式
datetime / zoneinfo 日期、时间和时区
collections Counterdefaultdictdeque
itertools 组合迭代器
re 正则表达式
subprocess 受控启动子进程
logging 结构化运行日志
argparse 命令行参数
concurrent.futures / asyncio 并发与异步

17. 延伸阅读