asyncio --- ตัวกำหนดเวลา I/O แบบอะซิงโครนัส

โมดูลนี้ให้ตัวกำหนดเวลาแบบ cooperative-multitasking สำหรับคอร์รูทีน async/await พร้อมกับโครงสร้างพื้นฐานสำหรับการซิงโครไนซ์ (ล็อก, อีเวนต์) และการเชื่อมต่อเครือข่าย TCP แบบไม่บล็อกผ่าน stream reader และ writer งานต่าง ๆ ทำงานพร้อมกันบน event loop เดียว โดยงานที่กำลังรันอยู่จะส่งคืนการควบคุมกลับไปยัง loop ด้วย await

ตัวอย่าง:

import asyncio

async def blink(led, period_ms):
    while True:
        led.on()
        await asyncio.sleep_ms(5)
        led.off()
        await asyncio.sleep_ms(period_ms)

async def main(led1, led2):
    asyncio.create_task(blink(led1, 700))
    asyncio.create_task(blink(led2, 400))
    await asyncio.sleep_ms(10_000)

# Running on an OpenMV Cam
from machine import LED
asyncio.run(main(LED(1), LED(2)))

ฟังก์ชันหลัก

asyncio.create_task(coro: Coroutine) Task

สร้างงานใหม่จากคอร์รูทีนที่กำหนดและกำหนดเวลาให้รัน

คืนค่าอ็อบเจกต์ Task ที่สอดคล้องกัน

asyncio.current_task() Task

คืนค่าอ็อบเจกต์ Task ที่เชื่อมโยงกับงานที่กำลังรันอยู่ในขณะนี้

asyncio.run(coro: Coroutine) Any

สร้างงานใหม่จากคอร์รูทีนที่กำหนดและรันจนเสร็จสมบูรณ์

คืนค่าที่ coro ส่งคืน

asyncio.sleep(t: float) None

หยุดรอเป็นเวลา t วินาที (สามารถเป็นทศนิยมได้)

นี่คือคอร์รูทีน

asyncio.sleep_ms(t: int) None

หยุดรอเป็นเวลา t มิลลิวินาที

นี่คือคอร์รูทีน และเป็นส่วนขยายของ MicroPython

ฟังก์ชันเพิ่มเติม

asyncio.wait_for(awaitable: Awaitable, timeout: float) Any

รอให้ awaitable เสร็จสมบูรณ์ แต่จะยกเลิกหากใช้เวลานานกว่า timeout วินาที หาก awaitable ไม่ใช่งาน ระบบจะสร้างงานจากมัน

หากเกิด timeout ระบบจะยกเลิกงานและยก asyncio.TimeoutError ขึ้น ซึ่งผู้เรียกควรดักจับไว้ งานจะได้รับ asyncio.CancelledError ซึ่งอาจละเว้นหรือดักจับโดยใช้ try...except หรือ try...finally เพื่อรันโค้ดทำความสะอาด

คืนค่าส่งคืนของ awaitable

นี่คือคอร์รูทีน

asyncio.wait_for_ms(awaitable: Awaitable, timeout: int) Any

คล้ายกับ wait_for() แต่ timeout เป็นจำนวนเต็มในหน่วยมิลลิวินาที

นี่คือคอร์รูทีน และเป็นส่วนขยายของ MicroPython

asyncio.gather(*awaitables, return_exceptions: bool = False) List

รัน awaitables ทั้งหมดพร้อมกัน awaitables ที่ไม่ใช่งานจะถูกยกระดับเป็นงาน

คืนค่าเป็นรายการของค่าส่งคืนของ awaitables ทั้งหมด

นี่คือคอร์รูทีน

class Task

class asyncio.Task

อ็อบเจกต์นี้ห่อหุ้มคอร์รูทีนไว้ในงานที่รันอยู่ งานสามารถรอด้วย await task ซึ่งจะรอให้งานเสร็จสมบูรณ์และคืนค่าส่งคืนของงาน

ไม่ควรสร้างงานโดยตรง ให้ใช้ create_task() ในการสร้างแทน

cancel() None

ยกเลิกงานโดยการฉีด asyncio.CancelledError เข้าไป งานอาจละเว้นข้อยกเว้นนี้ โค้ดทำความสะอาดอาจรันได้โดยการดักจับ หรือผ่าน try ... finally

class Event

class asyncio.Event

สร้างอีเวนต์ใหม่ที่สามารถใช้ซิงโครไนซ์งานได้ อีเวนต์เริ่มต้นในสถานะที่ถูกล้าง

is_set() bool

คืนค่า True หากอีเวนต์ถูกเซ็ต มิฉะนั้นคืนค่า False

set() None

เซ็ตอีเวนต์ งานใดที่รออยู่กับอีเวนต์จะถูกกำหนดเวลาให้รัน

หมายเหตุ: ต้องเรียกใช้จากภายในงาน ไม่ปลอดภัยที่จะเรียกใช้จาก IRQ, scheduler callback หรือเธรดอื่น ดู ThreadSafeFlag

clear() None

ล้างอีเวนต์

wait() None

รอให้อีเวนต์ถูกเซ็ต หากอีเวนต์ถูกเซ็ตแล้วจะคืนค่าทันที

นี่คือคอร์รูทีน

class ThreadSafeFlag

class asyncio.ThreadSafeFlag

สร้างแฟล็กใหม่ที่สามารถใช้ซิงโครไนซ์งานกับโค้ดที่รันนอก asyncio loop เช่น เธรดอื่น, IRQs หรือ scheduler callbacks แฟล็กเริ่มต้นในสถานะที่ถูกล้าง

set() None

เซ็ตแฟล็ก หากมีงานที่รอแฟล็กอยู่ งานนั้นจะถูกกำหนดเวลาให้รัน

clear() None

ล้างแฟล็ก ใช้เพื่อให้แน่ใจว่าแฟล็กที่อาจถูกเซ็ตไว้ก่อนหน้านี้ถูกล้างก่อนรอ

wait() None

รอให้แฟล็กถูกเซ็ต หากแฟล็กถูกเซ็ตแล้วจะคืนค่าทันที แฟล็กจะถูกรีเซ็ตโดยอัตโนมัติเมื่อคืนค่าจาก wait

แฟล็กสามารถรอได้โดยงานเดียวในแต่ละครั้งเท่านั้น

นี่คือคอร์รูทีน

class Lock

class asyncio.Lock

สร้างล็อกใหม่ที่สามารถใช้ประสานงานได้ ล็อกเริ่มต้นในสถานะปลดล็อก

นอกจากเมธอดด้านล่าง ล็อกยังสามารถใช้ใน async with ได้

locked() bool

คืนค่า True หากล็อกถูกล็อก มิฉะนั้นคืนค่า False

acquire() bool

รอให้ล็อกอยู่ในสถานะปลดล็อกจากนั้นล็อกในลักษณะอะตอมมิก งานเดียวเท่านั้นที่สามารถครอบครองล็อกได้ในแต่ละครั้ง

นี่คือคอร์รูทีน

release() None

ปล่อยล็อก หากมีงานรออยู่กับล็อก งานถัดไปในคิวจะถูกกำหนดเวลาให้รันและล็อกยังคงล็อกอยู่ มิฉะนั้น ไม่มีงานรออยู่และล็อกจะกลายเป็นปลดล็อก

การเชื่อมต่อ TCP stream

asyncio.open_connection(host: str, port: int, ssl: ssl.SSLContext | bool | None = None) Tuple[Stream, Stream]

เปิดการเชื่อมต่อ TCP ไปยัง host และ port ที่กำหนด ที่อยู่ host จะถูกแก้ไขโดยใช้ socket.getaddrinfo() ซึ่งปัจจุบันเป็นการเรียกแบบบล็อก หาก ssl เป็นอ็อบเจกต์ ssl.SSLContext context นี้จะถูกใช้สร้าง transport; หาก ssl เป็น True จะใช้ context เริ่มต้น

คืนค่าเป็นคู่ของ stream: reader stream และ writer stream จะยก OSError เฉพาะซ็อกเก็ตหากไม่สามารถแก้ไขโฮสต์หรือสร้างการเชื่อมต่อได้

นี่คือคอร์รูทีน

asyncio.start_server(callback: Callable, host: str, port: int, backlog: int = 5, ssl: ssl.SSLContext | None = None) Server

เริ่ม TCP server บน host และ port ที่กำหนด callback จะถูกเรียกพร้อมการเชื่อมต่อที่เข้ามาและยอมรับ และจะส่ง 2 อาร์กิวเมนต์: reader และ writer stream สำหรับการเชื่อมต่อ

หาก ssl เป็นอ็อบเจกต์ ssl.SSLContext context นี้จะถูกใช้สร้าง transport

คืนค่าอ็อบเจกต์ Server

นี่คือคอร์รูทีน

class asyncio.Stream

นี่แสดงถึงการเชื่อมต่อ TCP stream เพื่อลดโค้ด คลาสนี้ใช้งานทั้ง reader และ writer และทั้ง StreamReader และ StreamWriter เป็น alias ของคลาสนี้

get_extra_info(v: str) Any

รับข้อมูลเพิ่มเติมเกี่ยวกับ stream ที่กำหนดโดย v ค่าที่ถูกต้องสำหรับ v ได้แก่: peername

close() None

ปิด stream

wait_closed() None

รอให้ stream ปิด

นี่คือคอร์รูทีน

read(n: int = -1) bytes

อ่านไม่เกิน n ไบต์และคืนค่า หาก n ไม่ได้ระบุหรือเป็น -1 จะอ่านไบต์ทั้งหมดจนถึง EOF ค่าที่ส่งคืนจะเป็นอ็อบเจกต์ bytes ว่างหากพบ EOF ก่อนอ่านไบต์ใด ๆ

นี่คือคอร์รูทีน

readinto(buf: bytearray | memoryview) int

อ่านไม่เกิน n ไบต์ลงใน buf โดย n เท่ากับความยาวของ buf

คืนค่าจำนวนไบต์ที่อ่านลงใน buf

นี่คือคอร์รูทีน และเป็นส่วนขยายของ MicroPython

readexactly(n: int) bytes

อ่าน n ไบต์พอดีและคืนค่าเป็นอ็อบเจกต์ bytes

ยก EOFError หาก stream สิ้นสุดก่อนอ่านครบ n ไบต์

นี่คือคอร์รูทีน

readline() bytes

อ่านบรรทัดและคืนค่า

นี่คือคอร์รูทีน

write(buf: bytes) None

สะสม buf ไปยังบัฟเฟอร์เอาต์พุต ข้อมูลจะถูก flush เมื่อเรียก Stream.drain() เท่านั้น แนะนำให้เรียก Stream.drain() ทันทีหลังจากเรียกฟังก์ชันนี้

drain() None

Drain (เขียน) ข้อมูลเอาต์พุตที่บัฟเฟอร์ไว้ทั้งหมดออกไปยัง stream

นี่คือคอร์รูทีน

class asyncio.Server

นี่แสดงถึงคลาส server ที่คืนค่าจาก start_server() สามารถใช้ใน async with เพื่อปิด server เมื่อออก

close() None

ปิด server

wait_closed() None

รอให้ server ปิด

นี่คือคอร์รูทีน

Event Loop

asyncio.get_event_loop() Loop

คืนค่า event loop ที่ใช้กำหนดเวลาและรันงาน ดู Loop

asyncio.new_event_loop() Loop

รีเซ็ต event loop และคืนค่า

หมายเหตุ: เนื่องจาก MicroPython มี event loop เดียว ฟังก์ชันนี้จึงเพียงรีเซ็ตสถานะของ loop ไม่ได้สร้างใหม่

class asyncio.Loop

นี่แสดงถึงอ็อบเจกต์ที่กำหนดเวลาและรันงาน ไม่สามารถสร้างได้ ให้ใช้ get_event_loop() แทน

create_task(coro: Coroutine) Task

สร้างงานจาก coro ที่กำหนดและคืนค่าอ็อบเจกต์ Task ใหม่

run_forever() None

รัน event loop จนกว่าจะเรียก stop()

run_until_complete(awaitable: Awaitable) Any

รัน awaitable ที่กำหนดจนเสร็จสมบูรณ์ หาก awaitable ไม่ใช่งานจะถูกยกระดับเป็นงาน

stop() None

หยุด event loop

close() None

ปิด event loop

set_exception_handler(handler: Callable) None

ตั้งค่า exception handler ที่จะเรียกเมื่องานยกข้อยกเว้นที่ไม่ถูกดักจับ handler ควรรับสองอาร์กิวเมนต์: (loop, context)

get_exception_handler() Callable | None

รับ exception handler ปัจจุบัน คืนค่า handler หรือ None หากไม่มี handler ที่กำหนดเอง

default_exception_handler(context: dict) None

default exception handler ที่ถูกเรียก

call_exception_handler(context: dict) None

เรียก exception handler ปัจจุบัน อาร์กิวเมนต์ context จะถูกส่งผ่านและเป็น dictionary ที่มีคีย์: 'message', 'exception', 'future'