Python / Async Python үндэс

Async Python үндэс

Та вэб сайтаас өгөгдөл татахдаа хариу ирэхийг хүлээж суудаг — энэ хугацаанд компьютер юу ч хийхгүй байна. Async programming нь хүлээх хугацаанд өөр ажил хийх боломж олгодог. FastAPI нь async дээр суурилсан тул энэ ойлголт маш чухал.

Синхрон ба асинхрон харьцуулбал

Ресторанд захиалга хийхтэй зүйрлэвэл: синхрон зөлөг нэг хүний захиалгыг хүлээж аваад гал тогоонд өгч, хоол бэлэн болтол зогсоод, авч ирнэ — дараагийн зочинд ойртдоггүй. Асинхрон зөлөг олон хүний захиалгыг зэрэг авч, хоол бэлэн болох зуур өөр зочинд үйлчилнэ.

python
import asyncio
import time

# Синхрон — нэг нэгээр хүлээнэ
def синхрон_татах(url):
    time.sleep(2)   # хүлээлтийг дуурайлгав
    return f"{url} — татагдлаа"

эхлэл = time.time()
print(синхрон_татах("сайт-А"))
print(синхрон_татах("сайт-Б"))
print(f"Нийт хугацаа: {time.time() - эхлэл:.1f}с")   # ~4 секунд

# Асинхрон — зэрэгцүүлэн хүлээнэ
async def асинхрон_татах(url):
    await asyncio.sleep(2)   # хүлээх үед өөр ажил хийнэ
    return f"{url} — татагдлаа"

async def гол():
    эхлэл = time.time()
    а, б = await asyncio.gather(
        асинхрон_татах("сайт-А"),
        асинхрон_татах("сайт-Б"),
    )
    print(а)
    print(б)
    print(f"Нийт хугацаа: {time.time() - эхлэл:.1f}с")   # ~2 секунд

asyncio.run(гол())

Хоёр татах үйлдэл зэрэгцэн гүйцэтгэгдсэн тул 4 биш 2 секунд л зарцуулна — async-ийн гол давуу тал энэ.

async ба await түлхүүр үгс

python
import asyncio

# async def — асинхрон функц тодорхойлно
async def мэндлэх(нэр: str, хугацаа: float):
    await asyncio.sleep(хугацаа)   # await — дуусахыг хүлээнэ
    print(f"Сайн уу, {нэр}!")

async def гол():
    # gather — олон coroutine-ийг зэрэг ажиллуулна
    await asyncio.gather(
        мэндлэх("Болд", 1.0),
        мэндлэх("Сарнай", 0.5),
        мэндлэх("Төгс", 1.5),
    )

asyncio.run(гол())
# Сайн уу, Сарнай!   (0.5с дараа)
# Сайн уу, Болд!     (1.0с дараа)
# Сайн уу, Төгс!     (1.5с дараа)

async def функцийг шууд дуудаж болохгүй — await эсвэл asyncio.run() шаарддаг.

FastAPI-д async ашиглах

FastAPI нь async def болон энгийн def хоёуланг дэмждэг:

python
from fastapi import FastAPI
import asyncio
import httpx   # async HTTP client — pip install httpx

app = FastAPI()

@app.get("/нэгэн_зэрэг")
async def олон_эх_сурвалж():
    async with httpx.AsyncClient() as client:
        # Хоёр хүсэлтийг зэрэгцүүлэн илгээнэ
        хариу_а, хариу_б = await asyncio.gather(
            client.get("https://httpbin.org/delay/1"),
            client.get("https://httpbin.org/delay/1"),
        )
    return {
        "А_статус": хариу_а.status_code,
        "Б_статус": хариу_б.status_code,
        "тайлбар": "хоёулаа зэрэг дууслаа"
    }

@app.get("/энгийн")
def энгийн_endpoint():
    # IO-гүй, тооцооллын endpoint — энгийн def хангалттай
    return {"утга": sum(range(1_000_000))}

IO хүлээдэг (сүлжээ, файл, өгөгдлийн сан) endpoint-т async def ашиглах нь FastAPI-г хамгийн үр дүнтэй ажиллуулна.

asyncio.timeout — хугацааны хязгаар

Хэт удаан хариу буцаадаг хүсэлтэд хугацааны хязгаар тогтоох нь чухал:

python
import asyncio

async def удаан_ажил():
    await asyncio.sleep(10)
    return "дууслаа"

async def гол():
    try:
        async with asyncio.timeout(3):   # 3 секундаас илүүгүй
            үр_дүн = await удаан_ажил()
            print(үр_дүн)
    except asyncio.TimeoutError:
        print("Хугацаа дуусав — хариу ирсэнгүй")

asyncio.run(гол())
# Хугацаа дуусав — хариу ирсэнгүй

Async нь эхэндээ шинэ сэтгэлгээ шаарддаг боловч FastAPI, вэб хусах, өгөгдлийн сангийн ажиллагааг ойлгоход маш хэрэгтэй суурь мэдлэг.

Дараагийн хичээлд:

NumPy үндэс — тоон тооцоолол, массив үйлдлүүд, өгөгдлийн шинжилгээний суурь болох NumPy-г эхлэгчдэд ойлгомжтойгоор сурна.