Python 标准库是随解释器一起安装的模块集合,覆盖了文件系统、网络、编码、时间、并发、测试等日常开发的主要需求。它不依赖任何第三方包,因此也被视为 Python”开箱即用”能力的核心。
标准库的范围比想象中大——pydoc 的模块列表有 200 多个条目,其中 __future__、_thread 这类属于内部实现,不算对外 API。下面按用途挑出实际项目里用得最多的模块。
一个前置判断:标准库解决的是”通用能力”,不是”特定领域需求”。需要 HTTP 客户端、日期时间处理、JSON 解析这类事,先看标准库能不能满足;需要 ORM、深度学习框架、Web 框架时才引入第三方包。这个顺序能显著减少依赖数量。
文件与目录操作
pathlib
pathlib(3.4+)是现在处理路径的默认选择,它把路径变成对象,替代了 os.path 的字符串拼接。
from pathlib import Path
path = Path("data") / "input.txt"
print(path.name) # input.txt
print(path.suffix) # .txt
print(path.parent) # data
print(path.exists()) # False(当前目录下没有这个文件)判断和查找:
from pathlib import Path
print(Path(".").exists()) # True
for file in Path(".").glob("*.py"):
print(file.name)
print(list(Path(".").rglob("*.md"))[:3]) # 递归查找读写操作:
from pathlib import Path
target = Path("output.txt")
target.write_text("hello", encoding="utf-8")
print(target.read_text(encoding="utf-8")) # hello
target.unlink() # 清理,避免污染工作目录遍历目录树:
from pathlib import Path
for item in list(Path(".").iterdir())[:5]:
kind = "目录" if item.is_dir() else "文件"
print(f"{kind}: {item.name}")Path(__file__) 这个写法值得单独提:它取当前脚本文件所在目录,在写”配置和脚本放一起”的小工具时很常见。
from pathlib import Path
base = Path(__file__).resolve().parent
config_path = base / "config.toml"
print(config_path)注意 __file__ 前后各两个下划线,是 Python 内置变量,不是关键字。在交互式环境里它不存在,所以调试这段代码时要用 Path(".") 替代。
os
os 提供与操作系统直接交互的接口。凡是 pathlib 能做的,优先用 pathlib;os 剩下的独有价值主要是进程、环境变量和系统调用。
import os
print(os.getcwd()) # 当前工作目录
print(os.environ.get("HOME")) # 读环境变量
print(os.listdir(".")) # 列出目录内容
os.makedirs("output/logs", exist_ok=True) # 递归创建目录运行外部命令:
import subprocess
result = subprocess.run(
["python", "--version"],
capture_output=True,
text=True,
check=True,
)
print(result.stdout.strip())subprocess.run 传列表而不是字符串,可以避免 shell 注入。如果确实需要 shell 语法,用 shell=True,但此时必须自行校验输入。
环境变量的读写:
import os
os.environ["APP_ENV"] = "production"
print(os.getenv("APP_ENV")) # productionshutil
shutil 负责复制、移动、删除这类文件级操作——os 只管元数据和路径。
import shutil
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
(root / "source.txt").write_text("hello", encoding="utf-8")
(root / "source_dir").mkdir()
(root / "source_dir" / "a.txt").write_text("a", encoding="utf-8")
shutil.copy(root / "source.txt", root / "target.txt")
shutil.copytree(root / "source_dir", root / "target_dir") # 递归复制目录
shutil.make_archive(str(root / "backup"), "zip", root / "source_dir")
print(sorted(p.name for p in root.iterdir()))shutil.rmtree 没有确认机制,路径写错就是数据丢失。可以先 shutil.copytree 备份再删,或者用 shutil.disk_usage 检查空间。
网络与数据格式
json
json 是最常用的数据交换格式,json.dumps 序列化、json.loads 反序列化。
import json
data = {"name": "Alice", "age": 18, "tags": ["a", "b"]}
text = json.dumps(data, ensure_ascii=False, indent=2)
print(text)
obj = json.loads(text)
print(obj["name"]) # Aliceensure_ascii=False 让中文以原样输出而不是 \uXXXX 转义,可读性好很多。indent=2 用于日志和调试输出。
json.dump/json.load 直接操作文件:
import json
data = {"name": "Alice", "age": 18}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("data.json", "r", encoding="utf-8") as f:
obj = json.load(f)
print(obj["name"]) # Alice需要处理非标准 JSON(比如尾随逗号、单引号)时,json 的严格模式会报错,这时可以用 ast.literal_eval 兜底,但它只认字面量。
csv
csv 模块处理逗号分隔文件,正确处理引号、内嵌逗号和换行。
import csv
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["姓名", "年龄"])
writer.writerow(["Alice", 18])
with open("data.csv", "r", newline="", encoding="utf-8") as f:
reader = csv.reader(f)
for row in reader:
print(row)newline="" 是官方文档明确要求的写法——不设的话在 Windows 上会出现空行。
字典形式更常用:
import csv
with open("data.csv", "r", newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["姓名"], row["年龄"])urllib 与 http
标准库能发 HTTP 请求,只是 API 比较底层。
from urllib.request import urlopen
with urlopen("https://www.python.org") as resp:
print(resp.getcode()) # 200
print(resp.read(100).decode("utf-8"))urlopen 默认会跟随重定向、设置 User-Agent 之外的东西较少。实际项目里处理 JSON API 通常要自己加请求头:
from urllib.request import Request, urlopen
import json
req = Request(
"https://api.example.com/items",
headers={"User-Agent": "my-script/1.0", "Accept": "application/json"},
)
with urlopen(req, timeout=10) as resp:
payload = json.loads(resp.read().decode("utf-8"))timeout 必须显式指定,否则网络异常时可能一直挂着。
http.server 可以起一个本地测试服务器:
from http.server import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
body = b"Hello HTTP Server"
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
if __name__ == "__main__":
with HTTPServer(("localhost", 8000), MyHandler) as httpd:
print("Serving on http://localhost:8000")
httpd.serve_forever()它适合本地调试和测试,不要直接暴露到公网——没有并发处理,也没有安全防护。
socket
socket 是更底层的接口,需要自定义协议时用。
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("localhost", 8080))
server.listen(5)
with server:
conn, addr = server.accept()
with conn:
data = conn.recv(1024)
print("收到:", data.decode("utf-8"))
conn.send(b"Hello Client")with 的写法保证 socket 一定会被关闭,异常路径下也不会泄漏文件描述符。
email 与 smtplib
发邮件需要两者配合:email 构造消息,smtplib 负责投递。
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["Subject"] = "测试邮件"
msg["From"] = "sender@example.com"
msg["To"] = "receiver@example.com"
msg.set_content("这是正文内容")
with smtplib.SMTP("smtp.example.com", 587, timeout=30) as server:
server.starttls()
server.login("sender@example.com", "password")
server.send_message(msg)现代写法用 EmailMessage,比老的 MIMEText 简洁。starttls() 是必须的——不加密的话账号密码是明文传输的。
文本与数据处理
re
re 提供正则表达式。
import re
pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
email = "test@example.com"
print(re.match(pattern, email) is not None) # Truere.match 只从字符串开头匹配,re.search 在全文里找。用 re.fullmatch 要求整体匹配:
import re
print(re.fullmatch(r"\d{4}-\d{2}-\d{2}", "2026-10-24")) # True
print(re.match(r"\d+", "abc123")) # None,开头不匹配
print(re.search(r"\d+", "abc123").group()) # 123分组和替换:
import re
text = "2026-10-24 和 2026-01-01"
print(re.findall(r"\d{4}-\d{2}-\d{2}", text)) # ['2026-10-24', '2026-01-01']
print(re.sub(r"\d{4}", "2025", text))编译后的正则可以复用,大数据量时更快:
import re
pattern = re.compile(r"\d+")
print(pattern.findall("a1b22c333")) # ['1', '22', '333']collections 与 itertools
collections 提供容器类型,itertools 提供惰性迭代工具。
from collections import Counter, defaultdict, deque
print(Counter("aabbbc")) # Counter({'b': 3, 'a': 2, 'c': 1})
groups = defaultdict(list)
groups["x"].append(1)
print(dict(groups)) # {'x': [1]}
queue = deque([1, 2, 3])
queue.append(4)
print(queue.popleft()) # 1defaultdict(list) 比 setdefault 更简洁,也不会每次都白建一个空列表。
itertools 的组合函数是数据处理常用工具:
import itertools
print(list(itertools.product([1, 2], ["a", "b"])))
1. [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
print(list(itertools.combinations([1, 2, 3], 2))) # [(1, 2), (1, 3), (2, 3)]
print(list(itertools.permutations([1, 2], 2))) # [(1, 2), (2, 1)]
print(list(itertools.islice(range(10), 3, 6))) # [3, 4, 5]itertools.count() 是无限迭代器,配合 islice 取有限段:
import itertools
print(list(itertools.islice(itertools.count(10, 2), 4))) # [10, 12, 14, 16]hashlib
hashlib 提供 MD5、SHA-1、SHA-256、SHA-512 等哈希算法。
import hashlib
data = b"hello world"
print(hashlib.sha256(data).hexdigest())
print(hashlib.md5(data).hexdigest())增量哈希适合处理大文件,不必一次读进内存:
import hashlib
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
bigfile = Path(tmp) / "bigfile.bin"
bigfile.write_bytes(b"x" * 200000)
digest = hashlib.sha256()
with bigfile.open("rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
digest.update(chunk)
print(digest.hexdigest())安全提醒:MD5 和 SHA-1 已被证明存在碰撞漏洞,不能用于签名或完整性校验。密码存储要用 hashlib.pbkdf2_hmac 或 argon2 这类专用方案,而不是直接 sha256(password)——那样会被彩虹表直接反查。
base64 与 struct
import base64
encoded = base64.b64encode(b"hello")
print(encoded) # b'aGVsbG8='
print(base64.b64decode(encoded)) # b'hello'base64 是编码不是加密,任何人都能解码,别用它保护机密。
系统与运行时
sys
sys 提供解释器层面的信息和控制。
import sys
print(sys.argv) # 命令行参数,argv[0] 是脚本名
print(sys.version) # 版本信息
print(sys.platform) # 平台标识
print(sys.executable) # 解释器路径
print(sys.path) # 模块搜索路径sys.exit() 是脚本的正确退出方式,退出码 0 表示成功:
import sys
if len(sys.argv) < 2:
print("用法:script.py <参数>")
sys.exit(1)
print("收到参数:", sys.argv[1])platform 与 tempfile
import platform
print(platform.system()) # Linux / Windows / Darwin
print(platform.machine()) # x86_64
print(platform.python_version())tempfile 处理临时文件,比自己拼 /tmp/xxx 可靠——它会自动清理并避免名字冲突。
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
p = Path(tmp) / "scratch.txt"
p.write_text("data", encoding="utf-8")
print(p.exists()) # True
1. 离开 with 块,目录已自动删除单文件用 NamedTemporaryFile:
import tempfile
with tempfile.NamedTemporaryFile("w", encoding="utf-8", delete=False) as f:
f.write("hello")
path = f.name
print(path)argparse
命令行参数解析,argparse 是标准方案。
import argparse
parser = argparse.ArgumentParser(description="示例工具")
parser.add_argument("name", help="用户名")
parser.add_argument("--count", type=int, default=1, help="重复次数")
parser.add_argument("--verbose", action="store_true", help="输出详情")
args = parser.parse_args()
print(args.name, args.count, args.verbose)type=int 让参数自动转成整数,转换失败时 argparse 会给出友好报错并退出——比手动 int(argv[1]) 加 try/except 干净得多。
subprocess
import subprocess
out = subprocess.run(
["echo", "hello"],
capture_output=True,
text=True,
check=True,
)
print(out.stdout.strip())需要管道串联时用 Popen:
import subprocess
proc = subprocess.Popen(
["python", "-c", "print('from child')"],
stdout=subprocess.PIPE,
text=True,
)
stdout, _ = proc.communicate()
print(stdout.strip())时间与日期
datetime
datetime 是日期时间处理的主力模块。
from datetime import datetime, timedelta, date
now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S"))
future = now + timedelta(days=3)
print(future.date())
birthday = date(1990, 5, 20)
age = date.today().year - birthday.year
print(age)时区处理要用 zoneinfo(3.9+),不要自己加减小时:
from datetime import datetime
from zoneinfo import ZoneInfo
shanghai = datetime.now(ZoneInfo("Asia/Shanghai"))
utc = datetime.now(ZoneInfo("UTC"))
print(shanghai, utc)zoneinfo 依赖系统时区数据库,某些精简容器镜像里没有,需要装 tzdata 包。也可以用固定偏移:
from datetime import datetime, timezone, timedelta
tz = timezone(timedelta(hours=8))
print(datetime.now(tz))datetime.strptime 解析字符串时间:
from datetime import datetime
dt = datetime.strptime("2026-10-24 15:30:00", "%Y-%m-%d %H:%M:%S")
print(dt.year, dt.month, dt.day)time
time 是更底层的时间接口。
import time
timestamp = time.time() # Unix 时间戳(浮点秒)
print(time.localtime(timestamp))
print(time.strftime("%Y-%m-%d", time.localtime(timestamp)))
monotonic = time.monotonic() # 单调递增,不受系统时间调整影响
print(monotonic)测耗时时用 time.monotonic() 或 time.perf_counter(),不要用 time.time()——后者可能被 NTP 校时往回拨。
calendar
import calendar
print(calendar.isleap(2024)) # True
print(calendar.month(2024, 5))
print(calendar.weekday(2026, 10, 24)) # 5,星期五zoneinfo 之外的选择
处理”重复的时间”(夏令时回拨)时,标准库的做法是保持 datetime 为带时区的 aware 对象,用 fold 参数消歧:
from datetime import datetime
from zoneinfo import ZoneInfo
dt = datetime(2026, 11, 1, 1, 30, tzinfo=ZoneInfo("America/New_York"), fold=1)
print(dt)并发与并行
threading
threading 提供线程,适合 I/O 密集型任务。
import threading
import time
def task(name):
print(f"线程 {name} 开始")
time.sleep(0.1)
print(f"线程 {name} 结束")
threads = [threading.Thread(target=task, args=(f"T{i}",)) for i in range(3)]
for t in threads:
t.start()
for t in threads:
t.join()join() 等待线程结束,否则主程序可能在子线程完成前就退出。
线程间共享数据要用锁:
import threading
counter = 0
lock = threading.Lock()
def increment():
global counter
for _ in range(1000):
with lock:
counter += 1
threads = [threading.Thread(target=increment) for _ in range(4)]
for t in threads:
t.start()
for t in threads:
t.join()
print(counter) # 4000with lock: 写法比 lock.acquire()/lock.release() 更安全,异常时也会释放。
multiprocessing
multiprocessing 用多进程绕过 GIL,适合 CPU 密集型任务。
from multiprocessing import Process
def calc(num):
print(f"计算结果:{num * num}")
if __name__ == "__main__":
processes = [Process(target=calc, args=(i,)) for i in (5, 10)]
for p in processes:
p.start()
for p in processes:
p.join()if __name__ == "__main__": 这层保护必须写。Windows 和 macOS(spawn 启动方式)会重新导入主模块,没有保护会导致进程无限创建。
asyncio
asyncio 是异步 I/O 框架,单线程内通过事件循环调度协程。
import asyncio
async def fetch(name):
await asyncio.sleep(1) # 模拟 I/O 等待
return f"{name} 的结果"
async def main():
results = await asyncio.gather(fetch("A"), fetch("B"), fetch("C"))
for r in results:
print(r)
asyncio.run(main())asyncio.gather 并发执行多个协程,总耗时约等于最慢的那个,而不是三者之和。
asyncio.to_thread(3.9+)可以把同步阻塞函数丢到线程池:
import asyncio
import time
def blocking():
time.sleep(0.5)
return "done"
async def main():
result = await asyncio.to_thread(blocking)
print(result)
asyncio.run(main())queue
queue 提供线程安全的队列,用于生产消费模型。
import queue
import threading
q = queue.Queue(maxsize=5)
def producer():
for i in range(10):
q.put(i)
def consumer():
while True:
item = q.get()
print("消费:", item)
q.task_done() # 每次 get 对应一次 task_done
producer_t = threading.Thread(target=producer)
consumer_t = threading.Thread(target=consumer, daemon=True)
producer_t.start()
consumer_t.start()
producer_t.join() # 等生产者放完
q.join() # 等所有任务被消费处理完,然后正常退出注意 task_done() 要和 get() 配对调用,否则 q.join() 会一直等。
测试与调试
unittest
标准库的单元测试框架,不依赖 pytest。
import unittest
class TestAdd(unittest.TestCase):
def test_add(self):
self.assertEqual(1 + 2, 3)
def test_divide(self):
with self.assertRaises(ZeroDivisionError):
1 / 0
if __name__ == "__main__":
unittest.main()doctest
把测试写在文档字符串里,文档和测试合一。
import doctest
def add(a, b):
"""
计算两数之和。
>>> add(1, 2)
3
"""
return a + b
if __name__ == "__main__":
doctest.testmod()doctest.testmod() 会在文档里找 >>> 开头的示例并执行,输出不符就报错。适合给纯函数写示例。
timeit
测量代码片段的执行时间。
import timeit
t = timeit.timeit("[i * 2 for i in range(1000)]", number=10000)
print(f"耗时 {t:.4f} 秒")timeit 会自动排除启动开销,测的是纯执行时间,比手写 time.time() 前后相减准确。
pdb
内置调试器。
import pdb
def func(x):
pdb.set_trace() # 在这里停下
return x * 2
func(5)breakpoint()(3.7+)是更简洁的等价写法。
其他实用模块
tkinter
GUI 工具包,标准库自带。
import tkinter as tk
root = tk.Tk()
root.title("简单 GUI")
label = tk.Label(root, text="你好")
label.pack()
button = tk.Button(root, text="点击我", command=lambda: print("按钮被点击"))
button.pack()
root.mainloop()在无图形环境的服务器上会报 TclError,这是环境问题不是代码问题。
secrets
生成密码和随机令牌的安全模块,应该优先于 random。
import secrets
token = secrets.token_urlsafe(32)
print(token)
print(secrets.compare_digest("abc", "abc")) # True,常量时间比较statistics
import statistics
data = [1, 2, 3, 4, 100]
print(statistics.mean(data)) # 22
print(statistics.median(data)) # 3
print(statistics.stdev(data)) # 43.63configparser 与 tomllib
INI 格式用 configparser:
import configparser
config = configparser.ConfigParser()
config["Database"] = {"host": "localhost", "port": "3306"}
config.read("config.ini", encoding="utf-8")
print(config.get("Database", "host")) # localhostTOML 格式读用 tomllib(3.11+,只读),写用第三方 tomli-w:
import tomllib
with open("config.toml", "rb") as f:
config = tomllib.load(f)
print(config)注意 tomllib.load 要用 "rb" 二进制模式打开。
使用注意事项
- 先确认标准库能不能满足。只有确实需要特定领域能力时才加第三方依赖。
- 按需导入具体名字。
from pathlib import Path比import pathlib更快,也更明确用到哪个。 - 注意版本要求。
zoneinfo需要 3.9+,tomllib需要 3.11+,asyncio.to_thread需要 3.9+。写库时先定好支持的最低版本。 - 安全相关的用专用模块。密码哈希用
hashlib.pbkdf2_hmac,令牌生成用secrets,URL 解析用urllib.parse而不是手写正则。 pickle不安全。反序列化不可信来源的 pickle 数据等于执行任意代码,跨进程传输用 JSON。- 优先读官方文档。标准库细节多,
help()和 docs.python.org 是最准的来源。
相关文档
- Python 标准库全解析 —— 本篇
- Python 内置函数详解 ——
open、sorted等内置函数 - Python 35个关键字详解 ——
with、import等关键字