前端 Python 3.12

11. 标准库简介 II

美化输出、Template、struct、线程与队列、logging、weakref、collections 工具箱、decimal——深入「第二轮」常用库。

11.1 格式化与可读输出

reprlib

import reprlib

print(reprlib.repr(set("supercalifragilisticexpialidocious")))  # {'a', 'c', 'd', 'e', 'f', 'g', ...}

pprint

from pprint import pprint

pprint({"key": {"nested": [{"id": i} for i in range(3)]}})  # {'key': {'nested': [{'id': 0}, {'id': 1}, {'id': 2}]}}(更大时会多行缩进)

textwrap

import textwrap

s = "very long line " * 10
print(textwrap.fill(s, width=40))  # very long line ...(多行;每行宽度不超过 40)

locale

了解即可;服务端更推荐显式格式或只做 UTC + ISO。


11.2 模板:string.Template

当占位符与 str.format 的花括号/自定义 DSL 冲突时用:

from string import Template

sql_like = Template("SELECT $$literal, ${col} FROM t WHERE id = $id")
print(sql_like.safe_substitute(col="name", id="42"))  # SELECT $literal, name FROM t WHERE id = 42(缺键时未提供的占位符原样保留)

11.3 二进制:struct

import struct

packed = struct.pack("=IH", 42, 1024)  # = 表示「本机字节序但禁止填充」
value_u16, value_u32 = struct.unpack("=IH", packed)
print(value_u16, value_u32)  # 42 1024

11.4 线程与队列

import queue
import threading

q: queue.Queue[int] = queue.Queue()


def worker() -> None:
    while True:
        item = q.get()
        if item is None:
            q.task_done()
            break
        try:
            print("process", item)  # process 1(对每个非 None 任务一行)
        finally:
            q.task_done()


t = threading.Thread(target=worker, daemon=True)
t.start()
q.put(1)
q.put(None)
q.join()
t.join()

I/O 密集可用线程;CPU 密集需要 multiprocessing(或别语言运行时)。


11.5 日志:logging

import logging

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

log.info("started")
try:
    1 / 0
except ZeroDivisionError:
    log.exception("boom")  # ERROR + 栈

库代码只 getLogger,由应用配置 handler(文件、轮转、JSON 等)。


11.6 弱引用:weakref

实现「缓存不妨碍 GC」或注册表时才会碰到;日常不必手写。

import weakref


class Big:
    pass


cache: weakref.WeakValueDictionary[str, Big] = weakref.WeakValueDictionary()
obj = Big()
cache["k"] = obj
del obj
print(list(cache.keys()))  # [](弱引用目标已回收;若 GC 尚未运行则可能短暂仍有 'k')

11.7 collections 工具箱

工具场景
deque双端 O(1)
Counter频次
defaultdict缺省工厂
namedtuple / dataclass记录体
from collections import Counter, deque

print(Counter("abracadabra").most_common(3))  # [('a', 5), ('b', 2), ('r', 2)]

dq = deque(maxlen=3)
for i in range(5):
    dq.append(i)
print(list(dq))  # [2, 3, 4](maxlen=3,只保留最后 3 个)

11.8 精确十进制:decimal

from decimal import Decimal, ROUND_HALF_UP, getcontext

getcontext().prec = 6
x = Decimal("2.675")
print(x.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))  # 2.68

11.9 速记

  1. pprint / reprlib:对付巨大嵌套结构。
  2. logging:替代到处 print
  3. 钱:Decimal;数组算子:numpy(第三方)。

权威延伸11. Brief Tour of the Standard Library — Part II

On this page