0Pricing
Python Academy · Lekcja

Wzorce asynchronicznego wejścia-wyjścia w środowisku produkcyjnym

Proszę stosować asyncio do klientów HTTP, kolejek i rzeczywistych potoków przetwarzania.

Wzorce asynchronicznego wejścia-wyjścia w środowisku produkcyjnym to bezpłatna lekcja Python Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Python Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Python Academy zawiera 4 lekcji w sumie.

Najlepsze praktyki dotyczące pętli zdarzeń

Proszę zawsze używać asyncio.run() jako jedynego punktu wejścia. Należy unikać nieprzemyślanego mieszania kodu synchronicznego i asynchronicznego oraz nigdy nie blokować pętli zdarzeń długotrwałymi operacjami obliczeniowymi.

import asyncio

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

asyncio.run(main())

Pula połączeń

Proszę ponownie wykorzystywać połączenia zamiast otwierać nowe dla każdego żądania. Biblioteki takie jak asyncpg i aiohttp udostępniają wbudowane pule połączeń.

# 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()

Wzorzec producent-konsument z asyncio.Queue

asyncio.Queue rozdziela producentów i konsumentów działających jako współbieżne zadania.

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())

Ograniczanie liczby żądań za pomocą semafora

Proszę ograniczać liczbę współbieżnych żądań wychodzących, aby nie przeciążać zewnętrznych interfejsów API ani nie przekraczać ich limitów.

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])

Ponawianie z wykładniczym opóźnieniem

Proszę opakować operacje, które można ponawiać, w logikę opóźnień między próbami, aby prawidłowo obsługiwać przejściowe błędy.

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)

Kontrolowane zamykanie

Proszę przechwytywać asyncio.CancelledError w długo działających zadaniach i obsługiwać sygnały systemu operacyjnego, aby zamykanie przebiegało prawidłowo.

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")

Strumieniowanie odpowiedzi

Proszę używać generatorów asynchronicznych do strumieniowania dużych odpowiedzi bez ładowania ich w całości do pamięci.

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")

Zadania w tle w FastAPI

BackgroundTasks w FastAPI umieszcza zadania w kolejce, aby uruchomić je po wysłaniu odpowiedzi, dzięki czemu punkty końcowe działają szybko.

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"}

Wzorzec sygnału kontrolnego

Proszę uruchamiać okresowe zadanie w tle równolegle z główną pętlą serwera, używając 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()

Profilowanie kodu asynchronicznego

Proszę używać yappi lub py-spy do profilowania uwzględniającego kod asynchroniczny. Proszę włączyć tryb debugowania asyncio, aby otrzymywać ostrzeżenia o powolnych wywołaniach zwrotnych.

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

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

Unikanie typowych pułapek

Najważniejsze zasady: nie należy nigdy wywoływać blokującego kodu w pętli zdarzeń; zawsze należy oczekiwać na korutyny; podczas zamykania należy anulować zadania; należy używać pul połączeń i ograniczać współbieżność za pomocą semaforów.

import asyncio

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

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

Szybki test

Jaki mechanizm asyncio rozdziela producentów i konsumentów działających jako współbieżne zadania?

Podsumowanie

Wzorce asynchroniczne stosowane w środowisku produkcyjnym obejmują używanie pul połączeń, kontrolowanie współbieżności za pomocą semafora, implementowanie ponawiania z opóźnieniami, strumieniowanie dużych ilości danych, kontrolowane zamykanie po otrzymaniu sygnałów oraz uruchamianie zadań okresowych za pomocą create_task.

Często zadawane pytania

Czy lekcja „Wzorce asynchronicznego wejścia-wyjścia w środowisku produkcyjnym” jest bezpłatna?

Tak — pełny tekst „Wzorce asynchronicznego wejścia-wyjścia w środowisku produkcyjnym” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Python Academy, przejdź na CoddyKit PRO. Kurs Python Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wzorce asynchronicznego wejścia-wyjścia w środowisku produkcyjnym”?

Proszę stosować asyncio do klientów HTTP, kolejek i rzeczywistych potoków przetwarzania. Ćwiczysz Python Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Python Academy?

Nie wymagamy żadnego doświadczenia. Python Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Wzorce asynchronicznego wejścia-wyjścia w środowisku produkcyjnym”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Python Academy?

Tak. Każda lekcja Python Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Korutyny i pętla zdarzeń
  2. await, zadania i grupowanie
  3. Asynchroniczne menedżery kontekstu i iteratory
  4. Wzorce asynchronicznego wejścia-wyjścia w środowisku produkcyjnym
← Powrót do Python Academy