
Python 3.15 那些没上头条的特性TaskGroup 取消、线程安全迭代器、Counter XOR 与不可变 JSONPython 3.15 即将发布lazy imports 和 tachyon profiler 两大重磅特性已经刷屏各大技术媒体。但如果你只知道这两个大特性那你就错过了 3.15 版本中许多每天都在帮开发者省心省力的小改进。本文带你逐一盘点和实测这些没上头条但极其实用的 Python 3.15 新特性。本文所有代码均可在 Python 3.15.0b1 环境中运行测试。Asyncio TaskGroup.cancel()优雅地取消一组协程问题在 TaskGroup 中中途退出有多麻烦Python 3.11 引入的TaskGroup提供了结构化并发。但当你需要在满足某个条件时取消正在运行的一组任务时代码会变得相当绕importasynciofromcontextlibimportsuppressclassInterrupt(Exception):passasyncdefmain():withsuppress(Interrupt):asyncwithasyncio.TaskGroup()astg:tg.create_task(run())tg.create_task(run())ifawaitwait_for_signal():raiseInterrupt()这个模式利用了 TaskGroup 的一个特性——在 with 块内抛出异常会自动取消所有子任务。但我们必须自定义一个Interrupt异常再用contextlib.suppress来过滤掉它代码既不直观也不优雅。解决方案tg.cancel() 一行搞定Python 3.15 新增了TaskGroup.cancel()方法直接取消整个任务组且不抛出异常importasyncioasyncdefmain():asyncwithasyncio.TaskGroup()astg:tg.create_task(run())tg.create_task(run())ifawaitwait_for_signal():tg.cancel()# 优雅取消无异常抛出简洁、清晰、无黑魔法。如果你的代码中有类似的提前退出逻辑3.15 的这行改动能让代码整洁度提升一个档次。Context Manager 作为 Decorator终于支持 async 和 generator 了背景一直存在的双重身份Python 3.3 开始contextmanager装饰的上下文管理器也可以作为函数装饰器使用fromcontextlibimportcontextmanagerfromtimeimportperf_countercontextmanagerdefduration(message:str):startperf_counter()try:yieldfinally:print(f{message}elapsed{perf_counter()-start:.2f}seconds)duration(workload)defworkload():...# 自动计时但长期以来有一个严重限制——它不支持 async 函数、生成器和 async 生成器duration(async workload)asyncdefasync_workload():...# ❌ 只计时了协程创建没等到执行完成Python 3.15 的改进ContextDecorator现在会检查被装饰函数的类型确保装饰器覆盖函数的完整生命周期duration(async workload)asyncdefasync_workload():awaitasyncio.sleep(1)# ✅ 现在正确计时整个异步函数的执行时间duration(generator)defgen_workload():foriinrange(100):yieldi# ✅ 现在正确计时整个生成器的生命周期这个改动让contextmanager成为编写装饰器的最佳实践——比手动写functools.wraps更简洁比写类装饰器更安全。线程安全迭代器告别手动加锁痛点迭代器不是线程安全的Python 的迭代器默认不是线程安全的。在多线程环境中消费同一个生成器时你会遇到数据竞争和内部状态破坏defstream_events():whileTrue:yieldblocking_get_event()eventsstream_events()# 两个线程同时消费 events → 数据错乱传统的解决方案是用queue.Queue包装但这会改变代码架构。Python 3.15 三件套3.15 新增了三个线程安全迭代器工具1.threading.serialize_iterator— 包装任意迭代器为线程安全importthreadingfromconcurrent.futuresimportThreadPoolExecutor eventsthreading.serialize_iterator(stream_events())withThreadPoolExecutor()asexecutor:fut1executor.submit(consume,events)fut2executor.submit(consume,events)# ✅ 线程安全2.threading.synchronized_iterator— 装饰器版本直接应用到生成器函数threading.synchronized_iteratordefstream_events():whileTrue:yieldblocking_get_event()3.threading.concurrent_tee— 类似于itertools.tee但支持多线程并发消费source1,source2threading.concurrent_tee(squares(10),n2)withThreadPoolExecutor()asexecutor:executor.submit(consume,source1)executor.submit(consume,source2)# 两个线程互不干扰这三个工具解决了多线程编程中最常见的迭代器数据竞争问题。如果你的项目使用了 concurrent.futures 生成器强烈建议升级后立即替换。Counter 的 XOR 运算终于补齐了集合操作的最后一块拼图collections.Counter一直支持、-、、|四种集合运算。3.15 新增了^异或操作fromcollectionsimportCounter cCounter(a3,b1)dCounter(a1,b2)print(c^d)# Counter({a: 2, b: 1})异或 并集 - 交集相当于两个 Counter 中不重叠的计数之和。虽然实际应用场景不如和-广泛作者本人也承认但对于数据分析和统计场景来说补齐这个操作意味着 Counter 现在拥有完整的集合代数支持。不可变 JSON 对象frozendict json.loads 新参数Python 3.15 正式引入了frozendict不可变字典。配合json.loads新增的array_hook参数我们可以直接将 JSON 解析为完全不可变的数据结构fromtypesimportfrozendictimportjson resultjson.loads({a: [1, 2, 3, 4]},array_hooktuple,object_hookfrozendict)# result frozendict({a: (1, 2, 3, 4)})这个特性对以下场景非常有价值缓存键不可变对象可直接用作 dict 键或 set 元素配置管理防止运行时代码意外修改配置字典并发安全不可变对象天然线程安全总结与升级建议特性实用性推荐操作TaskGroup.cancel()⭐⭐⭐⭐⭐立即替换现有 workaroundContextManager decorator 改进⭐⭐⭐⭐重构现有装饰器代码线程安全迭代器⭐⭐⭐⭐⭐多线程项目必用Counter XOR⭐⭐⭐锦上添花frozendict array_hook⭐⭐⭐⭐配置和缓存场景强烈推荐Python 3.15 的 RC 版本已经可用生产环境建议等正式版发布后开始测试升级。你可以用pip install --pre python3.15.0rc1提前体验这些特性。延伸阅读如果你对 Python 3.15 的更大特性感兴趣可以查看 PEP 768lazy imports和 tachyon profiler 的详细信息。在线工具推荐如果你正在做 Python 项目并需要在线执行/测试代码欢迎访问 zidongai.com.cn提供免费的在线 Python 运行环境。