ไลบรารี asyncio ของ Python ถูกวิพากษ์วิจารณ์มากขึ้นเรื่อยๆ เนื่องจากข้อบกพร่องในการออกแบบและปัญหาการใช้งาน

ทีมชุมชน BigGo
ไลบรารี asyncio ของ Python ถูกวิพากษ์วิจารณ์มากขึ้นเรื่อยๆ เนื่องจากข้อบกพร่องในการออกแบบและปัญหาการใช้งาน

ไลบรารี asyncio ของ Python ที่เปิดตัวในปี 2012 เพื่อนำการเขียนโปรแกรมแบบอะซิงโครนัสมาสู่ภาษานี้ กำลังเผชิญกับการวิพากษ์วิจารณ์ที่เพิ่มมากขึ้นจากนักพัฒนาที่โต้แย้งว่าไลบรารีนี้มีข้อบกพร่องในการออกแบบและปัญหาการใช้งานมากเกินไป ไลบรารีนี้มีจุดประสงค์เพื่อเป็นทางเลือกแทนการใช้ threading แบบดั้งเดิมสำหรับการเขียนโปรแกรมแบบคอนเคอร์เรนต์ แต่การอภิปรายในชุมชนเผยให้เห็นความไม่พอใจอย่างแพร่หลายต่อการใช้งานจริง

กลไกการยกเลิกที่เสียหายสร้างปัญหาให้นักพัฒนา

หนึ่งในปัญหาที่สำคัญที่สุดของ asyncio คือระบบการยกเลิก ไม่เหมือนกับ threading แบบดั้งเดิมที่การยกเลิกเป็นเรื่องยากโดยธรรมชาติ asyncio ควรจะทำให้เรื่องนี้ง่ายขึ้น อย่างไรก็ตาม นักพัฒนารายงานว่ากลไกการยกเลิกมีปัญหาพื้นฐาน เมื่อ task ถูกยกเลิก สัญญาณการยกเลิกสามารถหายไปโดยไม่คาดคิด ทำให้การดำเนินการยังคงทำงานต่อไปอย่างไม่มีกำหนดแม้ว่าควรจะหยุดแล้ว สิ่งนี้สร้างสถานการณ์ที่แอปพลิเคชันค้างหรือใช้ทรัพยากรโดยไม่จำเป็น ทำให้การสร้างแอปพลิเคชันที่แข็งแกร่งและสามารถจัดการกับการขัดจังหวะได้อย่างสง่างามเป็นเรื่องยากมาก

ปัญหาการจัดการหน่วยความจำนำไปสู่ข้อผิดพลาดที่ลึกลับ

จุดเจ็บปวดสำคัญอีกประการหนึ่งคือข้อความแสดงข้อผิดพลาดที่มีชื่อเสียงว่า Task was destroyed but it is pending สิ่งนี้เกิดขึ้นเพราะ asyncio ไม่เก็บการอ้างอิงแบบแข็งแกร่งไปยัง task ซึ่งอาจทำให้ task ถูกเก็บขยะในขณะที่ยังคงทำงานอยู่ นักพัฒนาพบข้อผิดพลาดที่สับสนนี้บ่อยครั้งโดยไม่มีคำแนะนำที่ชัดเจนเกี่ยวกับวิธีแก้ไข สาเหตุหลักอยู่ที่ระบบการอ้างอิงแบบอ่อนของ asyncio ซึ่งออกแบบมาเพื่อป้องกันการรั่วไหลของหน่วยความจำ แต่กลับสร้างพฤติกรรมที่คาดเดาไม่ได้และยากต่อการแก้ไขข้อบกพร่อง

ความซับซ้อนของ API ระดับต่ำทำให้นักพัฒนาหงุดหงิด

API พื้นฐานของ socket และเครือข่ายใน asyncio ถูกวิพากษ์วิจารณ์ว่ามีความซับซ้อนโดยไม่จำเป็นและเต็มไปด้วยข้อผิดพลาด การดำเนินการง่ายๆ ที่ควรจะตรงไปตรงมากลับต้องการให้นักพัฒนาเข้าใจรายละเอียดที่ซับซ้อนเกี่ยวกับ event loop และ file descriptor ความซับซ้อนนี้ทำให้นักพัฒนายากที่จะเขียนโค้ดเครือข่ายที่เชื่อถือได้โดยไม่มีความรู้เชิงลึกเกี่ยวกับส่วนภายในของ asyncio

ปัญหาหลักของ asyncio ที่ระบุโดยชุมชน

ปัญหา คำอธิบาย ผลกระทบ
การยกเลิกที่เสียหาย สัญญาณการยกเลิกอาจหายไป ทำให้ task ทำงานต่อไปอย่างไม่มีกำหนด แอปพลิเคชันค้างหรือใช้ทรัพยากรโดยไม่จำเป็น
ข้อผิดพลาดการทำลาย Task "Task was destroyed but it is pending" เนื่องจาก weak references ข้อความแสดงข้อผิดพลาดที่สับสนและพฤติกรรมที่คาดเดาไม่ได้
API ระดับต่ำที่ซับซ้อน Socket และ networking APIs ต้องการความรู้เชิงลึกเกี่ยวกับการทำงานภายใน ยากต่อการเขียนโค้ดเครือข่ายที่เชื่อถือได้
ปัญหาการใช้งาน Queue การจัดการ producer-consumer patterns ที่ไม่ดี เกิด race conditions และแอปพลิเคชันค้าง

การใช้งาน Queue เพิ่มความซับซ้อนโดยไม่จำเป็น

แม้แต่รูปแบบพื้นฐานเช่นความสัมพันธ์ระหว่างผู้ผลิต-ผู้บริโภคโดยใช้ Queue ของ asyncio ก็มีปัญหา การใช้งาน queue ไม่สามารถจัดการกับสถานการณ์ทั่วไปได้อย่างสง่างาม เช่น การส่งสัญญาณอย่างเหมาะสมเมื่อไม่มีรายการเพิ่มเติมที่จะผลิต สิ่งนี้นำไปสู่ race condition และแอปพลิเคชันที่ค้าง บังคับให้นักพัฒนาต้องใช้งานวิธีแก้ไขปัญหาที่ซับซ้อนสำหรับสิ่งที่ควรจะเป็นรูปแบบการสื่อสารที่ง่าย

ชุมชนแสวงหาทางเลือกที่ดีกว่า

ชุมชน Python กำลังอภิปรายอย่างแข็งขันเกี่ยวกับทางเลือกอื่นสำหรับแนวทางของ asyncio นักพัฒนาบางคนสนับสนุนโซลูชัน monkey-patching ของ gevent ซึ่งอนุญาตให้โค้ดเดียวกันทำงานได้ทั้งในบริบทแบบซิงโครนัสและอะซิงโครนัส คนอื่นๆ ชี้ไปที่ภาษาเช่น Go ซึ่งจัดการกับ concurrency โดยไม่มีปัญหา function coloring ที่รบกวน asyncio

ฉันหวังจริงๆ ว่าชุมชนจะรวมตัวกันรอบ gevent - ไม่มี async/await แต่ทุกสิ่งที่เป็นไปได้ที่อาจบล็อกใน standard library จะถูก monkey-patch เพื่อ yield ไปยัง event loop

การอภิปรายยังสัมผัสถึงความกังวลที่กว้างขึ้นเกี่ยวกับการพัฒนาของ Python นักพัฒนาหลายคนรู้สึกว่า Python กลายเป็นภาษาที่บวมด้วยฟีเจอร์เช่น asyncio, type hints และ pattern matching ที่เพิ่มเข้ามาเพื่อให้ทันกับภาษาอื่นๆ แต่ไม่ได้บูรณาการเข้ากับปรัชญาหลักของ Python ได้ดี

ทางเลือกที่แนะนำโดยชุมชน

  • gevent: แนวทาง Monkey-patching ที่ช่วยให้ใช้โค้ดเดียวกันได้ทั้งแบบ sync/async
  • anyio: ชั้น Interface ที่อยู่บน asyncio เพื่อแก้ไขข้อบกพร่อง
  • Go-style concurrency: ภาษาโปรแกรมที่ไม่มีปัญหา "function coloring"
  • Stackful coroutines: คล้ายกับการใช้งานใน Lua แทนที่จะเป็นแบบ stackless

เส้นทางข้างหน้ายังไม่ชัดเจน

ในขณะที่ไลบรารีเช่น anyio พยายามให้อินเทอร์เฟซที่ดีกว่าบน asyncio ปัญหาการออกแบบพื้นฐานยังคงอยู่ สมาชิกชุมชนบางคนแนะนำว่า Python ต้องการการอัปเกรดเวอร์ชันหลักเพื่อแก้ไขปัญหาเหล่านี้อย่างเหมาะสม คล้ายกับที่การเปลี่ยนผ่านจาก Python 2 ไป 3 อนุญาตให้มีการเปลี่ยนแปลงที่ทำลายความเข้ากันได้ อย่างไรก็ตาม ความซับซ้อนของการดำเนินการดังกล่าวและบทเรียนที่ได้เรียนรู้จากการย้ายถิ่นที่ยากลำบากนั้นทำให้ไม่น่าจะเกิดขึ้นในอนาคตอันใกล้

สถานการณ์ของ asyncio เน้นย้ำถึงความท้าทายที่กว้างขึ้นในการออกแบบภาษา: วิธีเพิ่มฟีเจอร์สมัยใหม่โดยไม่ประนีประนอมความเรียบง่ายและความสง่างามที่ทำให้ภาษานั้นได้รับความนิยมตั้งแต่แรก สำหรับตอนนี้ นักพัฒนา Python ต้องทำงานรอบข้อจำกัดของ asyncio หรือพิจารณาแนวทางทางเลือกสำหรับการเขียนโปรแกรมแบบคอนเคอร์เรนต์

อ้างอิง: asyncio, a library with too many sharp corners