Python 3.15: TaskGroup.cancel — ยกเลิกกลุ่มงาน asyncio แบบตรง ๆ
เคยเขียน TaskGroup แล้วอยากหยุดทั้งกลุ่มเมื่อได้ผลลัพธ์แรก — วิธีเก่าคือโยน exception พิเศษแล้วกลืนตอนออกกลุ่ม ซึ่งอ่านยากครับ
Python 3.15 เพิ่ม TaskGroup.cancel (What’s new) ให้เรียกยกเลิกกลุ่มโดยตรงเมื่อเป้าหมายครบหรือไม่ต้องการงานที่เหลือแล้ว
ตัวอย่างโค้ดบางส่วนจากเอกสาร 3.15 (ยังไม่รันบนอินเทอร์พรีเตอร์ในบทความนี้):
import asyncio
async def race():
async with asyncio.TaskGroup() as tg:
t1 = tg.create_task(asyncio.sleep(2, result="slow"))
t2 = tg.create_task(asyncio.sleep(0.1, result="fast"))
await asyncio.wait({t1, t2}, return_when=asyncio.FIRST_COMPLETED)
tg.cancel() # ยกเลิกงานที่เหลือในกลุ่ม
ก่อนหน้านี้หลายคนสร้าง task ปลอมที่ raise แล้ว suppress — ตอนนี้ API ตั้งใจรองรับ early termination ชัดเจน (John Belmonte, gh-127214)
หมายเหตุ: ยังต้องเข้าใจ cancellation ของ awaitable ลูก — cancel() ของกลุ่มไม่ได้แปลว่า I/O ภายนอกทุกเส้นหยุดทันทีถ้าไม่เช็ก CancelledError
Recap
- อ่านสรุป
TaskGroup.cancelใน What’s new 3.15 - รีแฟกเตอร์ทริค “raise เพื่อหยุดกลุ่ม” ให้เป็น
tg.cancel()เมื่อขึ้น 3.15 - ทดสอบว่า cleanup ใน
finallyของงานลูกยังทำงาน - อย่าใช้ยกเลิกกลุ่มแทนการออกแบบ timeout ที่ชัดเจน