Python 常用标准库:datetime、collections 与 json

AI 辅助生成本文由 AI 起草并经人工核查,示例均标明软件版本;发现错误请以官方文档为准。

Python 3.13

Python 的标准库覆盖面很广。这一篇挑日常最高频的几组:时间、集合工具、环境变量与子进程。

环境准备

示例在 Python 3.13 下验证,全部为内置模块,无需安装。

datetime:时间与日期

from datetime import date, datetime, timedelta, timezone

today = date.today()                    # 2026-11-02
now = datetime.now()                    # 本地时间(不带时区)
utc = datetime.now(timezone.utc)        # 带时区

时间计算用 timedelta:

tomorrow = today + timedelta(days=1)
last_week = now - timedelta(weeks=1)
diff = datetime(2026, 12, 1) - now      # timedelta
diff.days                               # 相差天数

格式化与解析:

now.strftime("%Y-%m-%d %H:%M:%S")       # '2026-11-02 14:30:00'
now.isoformat(timespec="seconds")       # '2026-11-02T14:30:00'

datetime.strptime("2026-11-02", "%Y-%m-%d")          # 按格式解析
datetime.fromisoformat("2026-11-02T14:30:00")        # 解析 ISO 字符串

时区(3.9+ 用内置 zoneinfo,不必装 pytz):

from zoneinfo import ZoneInfo

shanghai = datetime.now(ZoneInfo("Asia/Shanghai"))
utc_time = shanghai.astimezone(timezone.utc)         # 转成 UTC

时间戳:

now.timestamp()                         # 秒(float)
datetime.fromtimestamp(1762000000, tz=timezone.utc)

collections:更强的容器

Counter:计数

from collections import Counter

words = "a b a c a b".split()
counter = Counter(words)
counter["a"]              # 3,不存在的键返回 0(不是 KeyError)
counter.most_common(2)    # [('a', 3), ('b', 2)]
counter + Counter(["a"])  # 计数相加
counter.update(["a", "d"])

defaultdict:带默认值的字典

from collections import defaultdict

groups = defaultdict(list)          # 访问不存在的键时自动创建 list
for name, team in [("a", "red"), ("b", "blue"), ("c", "red")]:
    groups[team].append(name)
# {'red': ['a', 'c'], 'blue': ['b']}

计数用 defaultdict(int),嵌套结构用 defaultdict(dict)。注意默认值工厂不能带参数,需要默认值时自己写 lambda: 1。

deque:双端队列

from collections import deque

queue = deque(["a", "b"])
queue.append("c")          # 右端入队
queue.popleft()            # 'a',左端出队(list.pop(0) 是 O(n))
queue.appendleft("z")
queue.rotate(1)

history = deque(maxlen=3)  # 固定长度,满了自动丢最老的

namedtuple

from collections import namedtuple

Row = namedtuple("Row", ["id", "name"])
r = Row(1, "a")
r.name          # 'a'
r._replace(id=2)

新代码优先用 typing.NamedTuple(支持注解)。

os / sys:环境信息

import os, sys

os.getenv("API_KEY")                 # 读环境变量,不存在返回 None
os.getenv("PORT", "8000")            # 带默认值
os.environ["API_KEY"] = "..."        # 设置(只影响当前进程)

sys.argv                             # 命令行参数列表,argv[0] 是脚本名
sys.version_info                     # 版本信息
sys.exit(1)                          # 退出码

os.path 能做的事 pathlib 都能做,新代码统一用 pathlib(见文件读写那一篇)。

subprocess:调用外部命令

import subprocess

result = subprocess.run(
    ["git", "rev-parse", "HEAD"],
    capture_output=True, text=True, check=True,
)
result.stdout.strip()      # commit hash
  • 用列表传参数,不要用 shell=True 拼字符串(避免命令注入)。
  • check=True 让非 0 退出码抛 CalledProcessError。
  • text=True 直接拿到字符串而不是 bytes。

random 与 secrets

import random, secrets

random.choice(["a", "b"])            # 随机选一个
random.sample(range(100), 5)         # 不重复抽 5 个
random.randint(1, 10)

secrets.token_urlsafe(32)            # 生成令牌:密码学安全,别用 random
secrets.choice(["a", "b"])

只要涉及令牌、密码、会话 ID,一律用 secrets。

shutil:文件操作

import shutil

shutil.copy2("a.txt", "backup/a.txt")     # 复制并保留元数据
shutil.move("a.txt", "archive/")
shutil.rmtree("tmp/")                     # 递归删除目录
shutil.make_archive("dist", "zip", "build/")

常见错误与注意事项

1. naive datetime 与 aware datetime 混用

不带时区的 datetime.now() 和带时区的 datetime.now(timezone.utc) 相减会报 TypeError。统一:内部存 UTC(aware),显示时再转本地。

2. 用 time.time() 手算日期

跨时区、闰年、夏令时都会出错,用 datetime + timedelta。

3. dict.get 与 defaultdict 混用

defaultdict 访问不存在的键会写入该键,if key in d 的语义会变(访问过就存在了)。

4. subprocess 拼字符串

subprocess.run(f"cat {filename}", shell=True)   # 危险:文件名含空格或分号就出事

用列表:["cat", filename]。

5. 用 random 生成令牌

random 是伪随机、可预测。令牌用 secrets。

小结

  • 时间用 datetime + timedelta,时区用 zoneinfo,存储统一 UTC。
  • 计数用 Counter,分组用 defaultdict,队列与滑动窗口用 deque。
  • 配置读 os.getenv,参数读 sys.argv(复杂场景见 argparse)。
  • 外部命令用 subprocess.run(列表, check=True);令牌用 secrets。

下一步