Python 中文教程

标准库巡礼

不逐个讲 API,只告诉你某个需求该找哪个模块,再看几个最常用的例子。

  • 第 10 章 · 工程实践
  • 34 分钟
  • 10 组对比

模块地图

Python 标准库覆盖面很广。遇到需求先查这张表,再去翻文档。

按需求找模块
PythonJava说明
pathlib、os、shutiljava.nio.file路径和文件操作
subprocessProcessBuilder运行外部命令
tempfileFiles.createTempFile临时文件
globFiles.newDirectoryStream通配符查找文件
sys、argparseargs、picocli命令行程序
rejava.util.regex正则表达式
math、random、statisticsMath、Random数学和随机数
datetimejava.time日期时间
timeSystem.currentTimeMillis、Thread.sleep时间戳和休眠
collectionsjava.utildeque、Counter、defaultdict
itertools、functoolsStream APIchain、groupby、lru_cache、partial
threading、concurrent.futuresjava.util.concurrent多线程
multiprocessing无多进程,绕开 GIL
asyncioCompletableFuture异步 I/O
loggingSLF4J日志
decimal、fractionsBigDecimal精确计算
unittest、doctestJUnit测试
urllib.requestjava.net.httpHTTP 请求,实际项目多用第三方库 requests
sqlite3JDBC + 驱动Python 内置了 SQLite
hashlib、base64、uuidMessageDigest、Base64、UUID摘要、编码和唯一 ID

文件和路径

路径操作首选 pathlib。/ 运算符用来拼接路径,读起来很直观。

路径操作

Python
from pathlib import Path

p = Path("src") / "app" / "main.py"
print(p)         # => src/app/main.py
print(p.name)    # => main.py
print(p.suffix)  # => .py
print(p.parent)  # => src/app
var p = Path.of("src", "app", "main.py");
System.out.println(p);  // => src/app/main.py
System.out.println(p.getFileName());  // => main.py
System.out.println(p.getParent());    // => src/app
对比项PythonJava
路径类型pathlib.Pathjava.nio.file.Path
拼接/ 运算符Path.of 或 resolve
文件名p.namep.getFileName()
扩展名p.suffix,含点需要自己截取
父目录p.parentp.getParent()

Path.cwd().glob("**/*.py") 递归查找文件。os.environ 读环境变量,shutil.copy 复制文件。

os 和 shutil 负责系统和文件操作。glob 用通配符查找文件。

Python
import glob
import os
import shutil
from pathlib import Path

Path("a.txt").write_text("hi")
shutil.copyfile("a.txt", "b.txt")  # 复制文件
shutil.move("b.txt", "c.txt")      # 移动文件

print(sorted(glob.glob("*.txt")))  # => ['a.txt', 'c.txt']
print(os.path.exists("c.txt"))     # => True
print(os.getcwd())                 # 当前工作目录

os.chdir() 切换目录,os.environ 读环境变量。运行外部命令用 subprocess.run(),比 os.system() 更安全,也能拿到输出。

命令行参数

sys.argv 是参数列表,第一项是脚本名,这和 Java 的 args 不同。需要选项解析时用 argparse,它会自动生成 --help。

Python
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("name")
parser.add_argument("-n", "--count", type=int, default=1)
args = parser.parse_args()

print(args.name, args.count)  # => Ann 2

向标准错误输出写 print("出错", file=sys.stderr),退出程序写 sys.exit(1),对应 System.err 和 System.exit(1)。

正则表达式

正则写在原始字符串 r"..." 里,不用双写反斜杠。

正则匹配和替换

Python
import re

text = "2026-10-30"
m = re.match(r"(\d+)-(\d+)", text)
print(m.group(1))                # => 2026
print(re.findall(r"\d+", text))  # => ['2026', '10', '30']
print(re.sub(r"-", "/", text))   # => 2026/10/30
var text = "2026-10-30";
var m = Pattern.compile("(\\d+)-(\\d+)")
    .matcher(text);
m.find();
System.out.println(m.group(1));  // => 2026
var r = text.replaceAll("-", "/");
System.out.println(r);  // => 2026/10/30
对比项PythonJava
正则写法r"\d+""\\d+",要双写反斜杠
匹配开头re.matchmatcher.lookingAt()
搜索任意位置re.searchmatcher.find()
查找全部re.findallmatcher.results()
替换re.subreplaceAll
分组语法相同(\d+)

re.match 只从开头匹配,re.fullmatch 要求整串匹配。简单替换直接用 str.replace。

数学和随机数

Python
import math
import random
import statistics

data = [1, 2, 3, 6]
print(math.ceil(2.1))           # => 3
print(math.log(1024, 2))        # => 10.0
print(statistics.mean(data))    # => 3
print(statistics.median(data))  # => 2.5
print(statistics.variance(data))

print(random.choice(["a", "b"]))     # 随机取一个
print(random.sample(range(100), 3))  # 不重复地取 3 个
print(random.random())               # 0 到 1 之间的浮点数
print(random.randrange(6))           # 0 到 5 之间的整数

random.shuffle 原地打乱列表。涉及安全的随机数要用 secrets 模块,相当于 SecureRandom。复杂的数值计算用第三方库 NumPy 和 SciPy。

访问网络

标准库的 urllib.request 能发 HTTP 请求,smtplib 能发邮件。

发起 HTTP 请求

Python
from urllib.request import urlopen

url = "https://example.com"
with urlopen(url) as resp:
    print(resp.status)   # => 200
    body = resp.read().decode("utf-8")

print("Example" in body)  # => True
var client = HttpClient.newHttpClient();
var req = HttpRequest
    .newBuilder(URI.create("https://example.com"))
    .build();
var resp = client.send(req,
    HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());  // => 200
对比项PythonJava
标准库urllib.requestjava.net.http.HttpClient
响应内容字节,要自己 decode由 BodyHandler 决定
常用第三方库requests、httpxOkHttp

实际项目基本都用 requests,一行就能写完:requests.get(url).json()。

日期和时间

date.today() 取当天日期,datetime.now() 取当前时间。

日期运算

Python
from datetime import date, timedelta

d = date(2026, 10, 30)
print(d + timedelta(days=7))  # => 2026-11-06
print(d.strftime("%Y/%m/%d")) # => 2026/10/30

days = (date(2027, 1, 1) - d).days
print(days)                   # => 63
var d = LocalDate.of(2026, 10, 30);
System.out.println(d.plusDays(7));  // => 2026-11-06
var fmt = DateTimeFormatter
    .ofPattern("yyyy/MM/dd");
System.out.println(d.format(fmt));  // => 2026/10/30

var end = LocalDate.of(2027, 1, 1);
var days = ChronoUnit.DAYS.between(d, end);
System.out.println(days);           // => 63
对比项PythonJava
日期类型date、datetimeLocalDate、LocalDateTime
加减天数d + timedelta(days=7)d.plusDays(7)
格式化d.strftime("%Y/%m/%d")DateTimeFormatter
日期差(a - b).daysChronoUnit.DAYS.between

datetime.now() 默认不带时区,服务端代码应该写 datetime.now(timezone.utc)。

并发

threading.Thread 是最基础的方式,start 启动线程,join 等待线程结束。

创建线程

Python
import threading

results = []
lock = threading.Lock()

def work(n):
    with lock:
        results.append(n * n)

threads = [
    threading.Thread(target=work, args=(i,))
    for i in range(3)
]
for t in threads:
    t.start()
for t in threads:
    t.join()

print(sorted(results))  # => [0, 1, 4]
var results = new ConcurrentLinkedQueue<Integer>();
var threads = new ArrayList<Thread>();

for (int i = 0; i < 3; i++) {
    int n = i;
    var t = new Thread(() -> results.add(n * n));
    t.start();
    threads.add(t);
}
for (var t : threads) {
    t.join();
}

var sorted = new TreeSet<>(results);
System.out.println(sorted);  // => [0, 1, 4]
对比项PythonJava
创建Thread(target=f, args=(1,))new Thread(runnable)
启动调用 start()调用 start()
加锁with lock:synchronized
线程安全队列queue.QueueBlockingQueue
同步工具Event、Semaphore、Condition有对应类
等待结束相同t.join()

多个线程协作时,优先让它们通过 queue.Queue 传递任务,这比到处加锁更不容易出错。

批量执行任务时用线程池,这是日常最常用的写法。

线程池

Python
from concurrent.futures import ThreadPoolExecutor

def square(n):
    return n * n

with ThreadPoolExecutor(max_workers=4) as pool:
    results = list(pool.map(square, [1, 2, 3]))

print(results)  # => [1, 4, 9]
var pool = Executors.newFixedThreadPool(4);
var tasks = new ArrayList<Future<Integer>>();
for (int n : List.of(1, 2, 3)) {
    tasks.add(pool.submit(() -> n * n));
}
for (var task : tasks) {
    System.out.println(task.get());
}
pool.shutdown();
对比项PythonJava
线程池ThreadPoolExecutorExecutors.newFixedThreadPool
关闭with 结束时自动关闭调用 shutdown()
CPU 密集任务受 GIL 限制,要用多进程多核并行
结果顺序pool.map 按输入顺序按 Future 列表顺序

with 结束时会等待所有任务完成,不用手动收尾。

异步编程

asyncio 用单线程事件循环处理大量 I/O。async def 定义协程,await 等待结果并让出控制权。官方教程没有讲它,但现代 Python 的网络框架大多基于它。

并发执行多个任务

Python
import asyncio

async def fetch(n):
    await asyncio.sleep(0.01)
    return n * n

async def main():
    results = await asyncio.gather(
        fetch(1), fetch(2), fetch(3))
    print(results)  # => [1, 4, 9]

asyncio.run(main())
static CompletableFuture<Integer> fetch(int n) {
    return CompletableFuture.supplyAsync(
        () -> n * n);
}

var tasks = List.of(fetch(1), fetch(2), fetch(3));
var results = tasks.stream()
    .map(CompletableFuture::join)
    .toList();
System.out.println(results);  // => [1, 4, 9]
对比项PythonJava
声明async def返回 CompletableFuture
等待结果awaitjoin() 或回调
并发执行asyncio.gatherCompletableFuture.allOf
程序入口asyncio.run(main())不需要
运行方式单线程事件循环线程池
适合场景相同大量并发 I/O

协程里不能调用会阻塞的函数,比如 time.sleep 和 requests.get,否则整个事件循环都会停住。要用 asyncio.sleep 和 httpx 这样的异步版本。

日志

记录日志

Python
import logging

logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)

log.info("端口 %d", 8080)
log.warning("磁盘快满了")
private static final Logger log =
    LoggerFactory.getLogger(App.class);

log.info("端口 {}", 8080);
log.warn("磁盘快满了");
对比项PythonJava
来源标准库 logging第三方 SLF4J
获取日志器getLogger(__name__)getLogger(App.class)
占位符%d、%s{}
警告级别log.warninglog.warn
延迟格式化相同消息真正输出时才格式化

不要在日志里用 f-string,否则每次调用都会格式化。默认级别是 WARNING,输出到标准错误。

日志级别从低到高是 DEBUG、INFO、WARNING、ERROR、CRITICAL,分别对应 log.debug() 到 log.critical()。配置既可以写在代码里,也可以从配置文件加载。

精确小数

金额计算不能用 float,要用 Decimal,对应 BigDecimal。构造时要传字符串。

精确计算

Python
from decimal import Decimal, ROUND_HALF_UP

a = Decimal("0.1")
b = Decimal("0.2")
print(a + b)  # => 0.3

cents = Decimal("0.01")
price = Decimal("2.675")
print(price.quantize(cents, ROUND_HALF_UP))  # => 2.68
var a = new BigDecimal("0.1");
var b = new BigDecimal("0.2");
System.out.println(a.add(b));  // => 0.3

var price = new BigDecimal("2.675")
    .setScale(2, RoundingMode.HALF_UP);
System.out.println(price);     // => 2.68
对比项PythonJava
类型DecimalBigDecimal
运算写法普通运算符add、multiply 等方法
舍入quantize(cents, ROUND_HALF_UP)setScale(2, HALF_UP)
全局精度getcontext().prec = 36每次传 MathContext
构造方式相同传字符串,避免浮点误差

金额计算不能用 float。构造时传浮点数会把误差一起带进来。

测试

标准库自带 unittest,结构和 JUnit 一样。运行命令是 python3 -m unittest。

单元测试

Python
import unittest

class MathTest(unittest.TestCase):
    def test_add(self):
        self.assertEqual(1 + 1, 2)

    def test_zero(self):
        with self.assertRaises(ZeroDivisionError):
            1 / 0
class MathTest {
    @Test
    void add() {
        assertEquals(2, 1 + 1);
    }

    @Test
    void zero() {
        assertThrows(ArithmeticException.class,
            () -> { int x = 1 / 0; });
    }
}
对比项PythonJava
框架标准库 unittest第三方 JUnit
测试标记方法名以 test 开头@Test 注解
测试类继承 unittest.TestCase普通类
断言相等assertEqual(a, b)assertEquals(a, b)
断言异常with assertRaises(E):assertThrows(E.class, ...)

实际项目大多用第三方的 pytest。测试写成普通函数,直接用 assert,比 unittest 简洁很多。

doctest 能运行文档字符串里的交互式示例,适合保证文档不过时。

Python
def double(n):
    """返回 n 的两倍。

    >>> double(4)
    8
    """
    return n * 2

import doctest
print(doctest.testmod().failed)  # => 0

其余模块

下面这些用到时再查,知道有就行。

  • 压缩归档:zlib、gzip、bz2、lzma、zipfile、tarfile
  • 性能测量:timeit 测小段代码,cProfile、profile 和 pstats 找程序热点
  • 高效数据结构:heapq 对应 PriorityQueue,bisect 对应 Collections.binarySearch,array 对应基本类型数组
  • 二进制数据:struct 的 pack 和 unpack,对应 ByteBuffer
  • 内存管理:CPython 用引用计数加循环垃圾回收,gc 模块可以手动触发,weakref 对应 WeakReference
  • 调整显示:textwrap 折行,pprint 美化输出数据结构,reprlib 缩略显示大对象
  • 文本模板:string.Template 的 substitute 和 safe_substitute,适合让用户自定义格式
  • 国际化:locale、gettext、codecs
  • 数据格式:csv、xml.etree.ElementTree、xml.dom、xml.sax
  • 邮件和远程调用:email、poplib、xmlrpc.client、xmlrpc.server

本章要点

  • 路径用 pathlib,日期用 datetime,精确小数用 decimal
  • 正则写在 r"..." 里,match 只匹配开头,search 匹配任意位置
  • 线程用 threading,线程池用 concurrent.futures,CPU 密集任务要用多进程,因为有 GIL
  • 大量并发 I/O 用 asyncio,协程里不能调用阻塞函数
  • 日志用 logging,占位符交给日志库格式化
  • 测试可以用 unittest,实际项目多用 pytest

官方原文:标准库简介标准库简介第二部分