วิธีใช้ asyncio ใน Python
ฟังก์ชันการเขียนโปรแกรมแบบอะซิงโครนัสของ Python หรือเรียกสั้น ๆ ว่า async ช่วยให้คุณสามารถเขียนโปรแกรมที่ทำงานได้มากขึ้นโดยไม่ต้องรอให้งานอิสระเสร็จสิ้น asyncio
ห้องสมุดรวมกับงูหลามจะช่วยให้คุณมีเครื่องมือที่จะใช้สำหรับการประมวลผล async ดิสก์หรือเครือข่าย I / O โดยไม่ต้องทำทุกอย่างอื่นรอ
asyncio
มีสองชนิดของ API สำหรับการรับมือกับการดำเนินงานไม่ตรงกัน: ระดับสูง และ ระดับต่ำ API ระดับสูงมีประโยชน์มากที่สุดและสามารถใช้ได้กับแอปพลิเคชันที่หลากหลายที่สุด API ระดับต่ำมีประสิทธิภาพ แต่ก็ซับซ้อนและใช้ไม่บ่อย
เราจะมุ่งเน้นไปที่ API ระดับสูงในบทความนี้ ในส่วนด้านล่างนี้เราจะอธิบายถึง API ระดับสูงที่ใช้กันมากที่สุดใน asyncio
และแสดงวิธีใช้สำหรับการดำเนินการทั่วไปที่เกี่ยวข้องกับงานอะซิงโครนัส
หากคุณยังใหม่กับ async ใน Python หรือคุณสามารถใช้การทบทวนวิธีการทำงานได้โปรดอ่านบทนำเกี่ยวกับ Python async ก่อนที่จะดำน้ำที่นี่
รันโครูทีนและงานใน Python
ตามปกติแล้วการใช้งานที่พบบ่อยที่สุดasyncio
คือการเรียกใช้ส่วนอะซิงโครนัสของสคริปต์ Python ของคุณ ซึ่งหมายถึงการเรียนรู้ที่จะทำงานกับโครูทีนและงานต่างๆ
ส่วนประกอบ async ของ Python รวมถึงโครูทีนและงานสามารถใช้ได้กับคอมโพเนนต์ async อื่น ๆ เท่านั้นไม่ใช่กับซิงโครนัส Python ทั่วไปดังนั้นคุณต้อง asyncio
เชื่อมช่องว่าง ในการดำเนินการนี้คุณใช้ asyncio.run
ฟังก์ชัน:
นำเข้า asyncioasync def หลัก ():
พิมพ์ ("รอ 5 วินาที")
สำหรับ _ ในช่วง (5):
รอ asyncio.sleep (1)
พิมพ์ (".")
พิมพ์ ("รอเสร็จแล้ว")
asyncio.run (หลัก ())
สิ่งนี้จะดำเนิน main()
ไปพร้อมกับโครูทีนใด ๆ ที่ main()
เริ่มทำงานและรอให้ผลลัพธ์กลับ
ตามกฎทั่วไปโปรแกรม Python ควรมีเพียง .run()
คำสั่งเดียวเช่นเดียวกับที่โปรแกรม Python ควรมีเพียง main()
ฟังก์ชันเดียว Async หากใช้อย่างไม่ระมัดระวังอาจทำให้ขั้นตอนการควบคุมของโปรแกรมอ่านยาก การมีจุดเข้าเพียงจุดเดียวไปยังรหัส async ของโปรแกรมจะช่วยป้องกันไม่ให้สิ่งต่างๆยุ่งยาก
ฟังก์ชัน Async ยังสามารถกำหนดเวลาเป็น งานหรืออ็อบเจ็กต์ที่ห่อโครูทีนและช่วยรันได้
async def my_task ():ทำอะไรสักอย่าง()
งาน = asyncio.create_task (my_task ())
my_task()
task
จะดำเนินการแล้วในวงเหตุการณ์ที่มีผลการดำเนินงานที่เก็บไว้ใน
หากคุณมีงานเพียงงานเดียวที่ต้องการให้ได้ผลลัพธ์คุณสามารถใช้ asyncio.wait_for(task)
เพื่อรอให้งานเสร็จสิ้นจากนั้นใช้ task.result()
เพื่อดึงผลลัพธ์ออกมา แต่ถ้าคุณกำหนดเวลาให้ดำเนินการหลายอย่างและคุณต้องการรอให้งาน ทั้งหมด เสร็จสิ้นให้ใช้ asyncio.wait([task1, task2])
เพื่อรวบรวมผลลัพธ์ (โปรดทราบว่าคุณสามารถกำหนดระยะหมดเวลาสำหรับการดำเนินการได้หากคุณไม่ต้องการให้การดำเนินการเหล่านี้ทำงานเกินระยะเวลาที่กำหนด)
จัดการ async event loop ใน Python
ควบคุมการใช้งานทั่วไปสำหรับ asyncio
คือการจัดการ async ห่วงเหตุการณ์ ห่วงเหตุการณ์เป็นวัตถุที่เรียกใช้ฟังก์ชัน async และการเรียกกลับ asyncio.run()
มันสร้างขึ้นโดยอัตโนมัติเมื่อคุณใช้ โดยทั่วไปคุณต้องการใช้ async event loop เพียงครั้งเดียวต่อโปรแกรมอีกครั้งเพื่อให้จัดการสิ่งต่างๆได้
หากคุณกำลังเขียนซอฟต์แวร์ขั้นสูงขึ้นเช่นเซิร์ฟเวอร์คุณจะต้องมีสิทธิ์เข้าถึงระดับล่างเพื่อไปยังลูปเหตุการณ์ ด้วยเหตุนี้คุณสามารถ "ยกฝากระโปรง" และทำงานโดยตรงกับภายในของลูปเหตุการณ์ แต่สำหรับงานง่ายๆคุณไม่จำเป็นต้องทำ
อ่านและเขียนข้อมูลด้วยสตรีมใน Python
สถานการณ์ที่ดีที่สุดสำหรับ async คือการดำเนินการเครือข่ายที่ใช้งานมานานโดยที่แอปพลิเคชันอาจบล็อกการรอให้ทรัพยากรอื่นส่งคืนผลลัพธ์ ด้วยเหตุ asyncio
นี้จึงเสนอสตรีมซึ่งเป็นกลไกระดับสูงสำหรับการดำเนินการ I / O เครือข่าย ซึ่งรวมถึงการทำหน้าที่เป็นเซิร์ฟเวอร์สำหรับคำขอเครือข่าย
asyncio
ใช้สองคลาส StreamReader
และ StreamWriter
เพื่ออ่านและเขียนจากเครือข่ายในระดับสูง หากคุณต้องการอ่านจากเครือข่ายคุณจะใช้ asyncio.open_connection()
เพื่อเปิดการเชื่อมต่อ ฟังก์ชันนั้นจะส่งคืนทูเพิล StreamReader
และ StreamWriter
อ็อบเจกต์และคุณจะใช้ .read()
และ .write()
เมธอดในแต่ละรายการเพื่อสื่อสาร
ที่จะได้รับการเชื่อมต่อจากโฮสต์ระยะไกล, asyncio.start_server()
การใช้งาน asyncio.start_server()
ฟังก์ชั่นใช้เวลาเป็นอาร์กิวเมนต์ฟังก์ชั่นการโทรกลับ, client_connected_cb
ซึ่งเรียกว่าเมื่อใดก็ตามที่ได้รับการร้องขอ ฟังก์ชันเรียกกลับนั้นรับอินสแตนซ์ StreamReader
และStreamWriter
เป็นอาร์กิวเมนต์ดังนั้นคุณสามารถจัดการตรรกะการอ่าน / เขียนสำหรับเซิร์ฟเวอร์ได้ (ดูตัวอย่างเซิร์ฟเวอร์ HTTP แบบธรรมดาที่ใช้ ไลบรารีasyncio
-driven aiohttp
ได้ที่นี่)
ซิงโครไนซ์งานใน Python
งานอะซิงโครนัสมักจะทำงานแยกกัน แต่บางครั้งคุณอาจต้องการให้งานเหล่านั้นสื่อสารกัน asyncio
จัดเตรียมคิวและกลไกอื่น ๆ สำหรับการซิงโครไนซ์ระหว่างงาน:
- คิว :
asyncio
คิวอนุญาตให้ฟังก์ชันอะซิงโครนัสจัดเรียงวัตถุ Python ที่จะใช้โดยฟังก์ชัน async อื่น ๆ ตัวอย่างเช่นเพื่อกระจายปริมาณงานระหว่างฟังก์ชันประเภทต่างๆตามพฤติกรรม - การซิงโครไนซ์แบบดั้งเดิม : ล็อกเหตุการณ์เงื่อนไขและเซมาโฟร์ในการ
asyncio
ทำงานเหมือนกับคู่หู Python ทั่วไป
สิ่งหนึ่งที่ควรทราบเกี่ยวกับวิธีการเหล่านี้ทั้งหมดก็คือวิธีนี้ ไม่ ปลอดภัยต่อเธรด นี่ไม่ใช่ปัญหาสำหรับงาน async ที่ทำงานในลูปเหตุการณ์เดียวกัน แต่ถ้าคุณพยายามแชร์ข้อมูลกับงานในลูปเหตุการณ์เธรดระบบปฏิบัติการหรือกระบวนการอื่นคุณจะต้องใช้ threading
โมดูลและวัตถุในการทำเช่นนั้น
นอกจากนี้หากคุณต้องการเรียก ใช้โครูทีน ข้ามขอบเขตเธรดให้ใช้ asyncio.run_coroutine_threadsafe()
ฟังก์ชันและส่งผ่านเหตุการณ์ลูปเพื่อใช้เป็นพารามิเตอร์
หยุดโครูทีนชั่วคราวใน Python
การใช้งานทั่วไปอีกอย่างหนึ่งของการใช้งานทั่วไป asyncio
และการพูดคุยที่ไม่ได้รับการกล่าวถึงคือการรอให้มีระยะเวลาโดยพลการภายในโครูทีน คุณไม่สามารถใช้ time.sleep()
สำหรับสิ่งนี้หรือคุณจะบล็อกทั้งโปรแกรม ให้ใช้แทน asyncio.sleep()
ซึ่งทำให้โครูทีนอื่น ๆ ทำงานต่อไปได้
ใช้ async ระดับล่างใน Python
สุดท้ายหากคุณคิดว่าแอปที่คุณกำลังสร้างอาจต้องใช้asyncio
ส่วนประกอบระดับล่างลองดูรอบ ๆ ก่อนที่คุณจะเริ่มเขียนโค้ด: มีโอกาสดีที่จะมีคนสร้างไลบรารี Python แบบ async ที่ทำในสิ่งที่คุณต้องการแล้ว
ตัวอย่างเช่นถ้าคุณต้องการสอบถาม DNS async ตรวจสอบ aiodns
ห้องสมุดและสำหรับการประชุม async SSH asyncSSH
มี ค้นหา PyPI ด้วยคีย์เวิร์ด“ async” (รวมถึงคีย์เวิร์ดอื่น ๆ ที่เกี่ยวข้องกับงาน) หรือตรวจสอบรายการ Awesome Asyncio ที่คัดสรรด้วยมือเพื่อดูแนวคิด