0Pricing
Python Academy · บทเรียน

รูปแบบอะซิงก์ I/O ในระบบจริง

ประยุกต์ใช้ asyncio กับไคลเอ็นต์ HTTP คิว และไปป์ไลน์ในโลกจริง

รูปแบบอะซิงก์ I/O ในระบบจริง เป็นบทเรียน Python Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Python Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน

แนวทางปฏิบัติที่ดีสำหรับลูปเหตุการณ์

ใช้ asyncio.run() เป็นจุดเข้าสู่โปรแกรมเพียงจุดเดียวเสมอ หลีกเลี่ยงการผสมโค้ดแบบซิงโครนัสและแบบอะซิงโครนัสอย่างไม่ระมัดระวัง และอย่าบล็อกลูปเหตุการณ์ด้วยงานประมวลผล CPU ที่ใช้เวลานาน

import asyncio

async def main():
    # Never: time.sleep() — blocks the event loop
    # Always: await asyncio.sleep()
    await asyncio.sleep(1)

asyncio.run(main())

การใช้กลุ่มการเชื่อมต่อ

ใช้การเชื่อมต่อเดิมซ้ำแทนการเปิดการเชื่อมต่อใหม่สำหรับแต่ละคำขอ ไลบรารีอย่าง asyncpg และ aiohttp มีกลุ่มการเชื่อมต่อในตัว

# pip install asyncpg
import asyncpg, asyncio

async def main():
    pool = await asyncpg.create_pool(
        dsn="postgresql://user:pass@host/db",
        min_size=5, max_size=20
    )
    async with pool.acquire() as conn:
        row = await conn.fetchrow("SELECT 1")
    await pool.close()

ผู้ผลิตและผู้บริโภคด้วย asyncio.Queue

asyncio.Queue แยกผู้ผลิตและผู้บริโภคที่ทำงานเป็นงานพร้อมกันออกจากกัน

import asyncio

async def producer(q):
    for i in range(5):
        await q.put(i)
        await asyncio.sleep(0.5)
    await q.put(None)  # sentinel

async def consumer(q):
    while (item := await q.get()) is not None:
        print(f"processing {item}")
        q.task_done()

async def main():
    q = asyncio.Queue()
    await asyncio.gather(producer(q), consumer(q))

asyncio.run(main())

การจำกัดอัตราด้วยเซมาฟอร์

จำกัดจำนวนคำขอขาออกที่ทำพร้อมกัน เพื่อไม่ให้ส่วนเชื่อมต่อโปรแกรมประยุกต์ภายนอกทำงานหนักเกินไปหรือทำให้เกินขีดจำกัดอัตรา

import asyncio, aiohttp

SEM = asyncio.Semaphore(10)  # 10 concurrent requests max

async def fetch(session, url):
    async with SEM:
        async with session.get(url) as r:
            return await r.json()

async def main(urls):
    async with aiohttp.ClientSession() as s:
        return await asyncio.gather(*[fetch(s, u) for u in urls])

ลองใหม่ด้วยการหน่วงเวลาแบบทวีคูณ

ครอบการดำเนินการที่สามารถลองใหม่ได้ด้วยตรรกะการหน่วงเวลา เพื่อจัดการความล้มเหลวชั่วคราวอย่างเหมาะสม

import asyncio

async def retry(coro_fn, retries=3, base=1):
    for attempt in range(retries):
        try:
            return await coro_fn()
        except Exception as e:
            if attempt == retries - 1: raise
            delay = base * 2 ** attempt
            await asyncio.sleep(delay)

การปิดระบบอย่างราบรื่น

ดักจับ asyncio.CancelledError ในงานที่ทำงานเป็นเวลานาน และจัดการสัญญาณของระบบปฏิบัติการเพื่อปิดระบบอย่างเรียบร้อย

import asyncio, signal

async def server():
    stop = asyncio.Event()
    loop = asyncio.get_running_loop()
    loop.add_signal_handler(signal.SIGINT, stop.set)
    await stop.wait()
    print("Shutting down gracefully")

การตอบกลับแบบสตรีม

ใช้ตัวสร้างแบบอะซิงโครนัสเพื่อส่งการตอบกลับขนาดใหญ่เป็นสตรีม โดยไม่ต้องโหลดทั้งหมดไว้ในหน่วยความจำ

import asyncio, aiohttp

async def stream(url):
    async with aiohttp.ClientSession() as s:
        async with s.get(url) as r:
            async for chunk in r.content.iter_chunked(4096):
                process(chunk)

async def process(chunk):
    await asyncio.sleep(0)
    print(len(chunk), "bytes")

งานเบื้องหลังใน FastAPI

BackgroundTasks ของ FastAPI จัดคิวงานให้ทำหลังจากส่งการตอบกลับแล้ว ทำให้จุดปลายทางตอบสนองได้รวดเร็ว

from fastapi import FastAPI, BackgroundTasks

app = FastAPI()

def send_email(to: str, body: str):
    # heavy synchronous work
    pass

@app.post("/register")
async def register(email: str, bg: BackgroundTasks):
    bg.add_task(send_email, email, "Welcome!")
    return {"status": "registered"}

รูปแบบสัญญาณชีพ

เรียกใช้งานเบื้องหลังเป็นระยะควบคู่ไปกับลูปเซิร์ฟเวอร์หลักโดยใช้ create_task

import asyncio

async def heartbeat():
    while True:
        print("alive")
        await asyncio.sleep(30)

async def main():
    asyncio.create_task(heartbeat())
    await serve_forever()

การทำโปรไฟล์โค้ดแบบอะซิงโครนัส

ใช้ yappi หรือ py-spy สำหรับการทำโปรไฟล์ที่รองรับโค้ดแบบอะซิงโครนัส เปิดโหมดดีบักของ asyncio เพื่อรับคำเตือนเกี่ยวกับการเรียกกลับที่ทำงานช้า

# Enable debug to catch slow callbacks:
# asyncio.run(main(), debug=True)

# PYTHONASYNCIODEBUG=1 python server.py
# logs: Executing <Task coroutine=...> took 0.150 seconds

การหลีกเลี่ยงข้อผิดพลาดที่พบบ่อย

กฎสำคัญมีดังนี้ อย่าเรียกโค้ดแบบบล็อกบนลูปเหตุการณ์ รอคอยโครูทีนเสมอ ยกเลิกงานเมื่อปิดระบบ ใช้กลุ่มการเชื่อมต่อ และจำกัดการทำงานพร้อมกันด้วยเซมาฟอร์

import asyncio

async def bad():
    import time
    time.sleep(2)        # blocks the entire event loop!

async def good():
    await asyncio.sleep(2)  # yields control

ตรวจสอบความเข้าใจอย่างรวดเร็ว

โครงสร้างพื้นฐานใดของ asyncio ที่แยกผู้ผลิตและผู้บริโภคซึ่งทำงานเป็นงานพร้อมกันออกจากกัน

สรุปทบทวน

รูปแบบโค้ดแบบอะซิงโครนัสสำหรับใช้งานจริง ได้แก่ ใช้กลุ่มการเชื่อมต่อ ควบคุมการทำงานพร้อมกันด้วย Semaphore ใช้การลองใหม่และการหน่วงเวลา ส่งข้อมูลขนาดใหญ่เป็นสตรีม ปิดระบบอย่างราบรื่นเมื่อได้รับสัญญาณ และเรียกงานเป็นระยะด้วย create_task

คำถามที่พบบ่อย

บทเรียน “รูปแบบอะซิงก์ I/O ในระบบจริง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “รูปแบบอะซิงก์ I/O ในระบบจริง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Python Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบอะซิงก์ I/O ในระบบจริง”

ประยุกต์ใช้ asyncio กับไคลเอ็นต์ HTTP คิว และไปป์ไลน์ในโลกจริง คุณปฏิบัติ Python Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Python Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Python Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “รูปแบบอะซิงก์ I/O ในระบบจริง” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Python Academy นี้ได้ไหม

ได้ บทเรียน Python Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. โครูทีนและลูปเหตุการณ์
  2. await งาน และการรวบรวมงาน
  3. ตัวจัดการบริบทและตัววนซ้ำแบบอะซิงก์
  4. รูปแบบอะซิงก์ I/O ในระบบจริง
← กลับไปที่ Python Academy