Ejen AI · Pelajaran

Python Tak Segerak untuk Pembangun Ejen

Asas asyncio, async def, await, gelung peristiwa — model mental tak segerak.

Pelajaran 1 daripada 413 langkah

Python Tak Segerak untuk Pembangun Ejen ialah pelajaran Ejen AI percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Ejen AI, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.

Mengapa Tak Segerak untuk Ejen?

Ejen membuat banyak panggilan yang terikat I/O: API LLM, permintaan web dan pertanyaan pangkalan data. Kod segerak menunggu tanpa melakukan kerja semasa panggilan ini selesai. Kod tak segerak menjalankan kerja lain sepanjang tempoh menunggu itu, lalu meningkatkan daya pemprosesan dengan ketara.

Asas Tak Segerak: async def dan await

async def mengisytiharkan fungsi korutin. await menggantung pelaksanaan sehingga operasi yang ditunggu selesai, sekali gus membolehkan gelung peristiwa menjalankan korutin lain sementara itu.

import asyncio

async def fetch_data(source: str) -> str:
    print(f'Starting fetch from {source}')
    await asyncio.sleep(1)  # Simulates a network call
    print(f'Finished fetch from {source}')
    return f'Data from {source}'

async def main():
    # Sequential: takes 2 seconds total
    result1 = await fetch_data('source-A')
    result2 = await fetch_data('source-B')
    print('Sequential results:', result1, result2)

asyncio.run(main())

# asyncio.run() starts the event loop and runs main()
# It is the entry point for async programs

Gelung Peristiwa

gelung peristiwa ialah teras asyncio. Ia mengurus baris gilir korutin dan panggilan balik I/O, lalu menjalankannya apabila sudah bersedia. Semua kod tak segerak berjalan dalam gelung peristiwa pada satu Thread sahaja.

import asyncio

async def task_a():
    print('Task A: start')
    await asyncio.sleep(2)
    print('Task A: done')

async def task_b():
    print('Task B: start')
    await asyncio.sleep(1)
    print('Task B: done')

async def main():
    # asyncio.gather runs both tasks concurrently
    # Total time: ~2 seconds (not 3)
    await asyncio.gather(task_a(), task_b())
    print('Both tasks complete')

# Expected output order:
# Task A: start
# Task B: start
# Task B: done   <- after 1s
# Task A: done   <- after 2s
# Both tasks complete
asyncio.run(main())

Korutin berbanding Thread

Thread bersifat koperatif: ia menyerahkan kawalan secara jelas menggunakan await. Thread bersifat prapintas: OS boleh bertukar antara Thread pada bila-bila masa. Korutin lebih ringan, tidak menghadapi masalah GIL untuk I/O dan lebih mudah difahami.

import asyncio
import threading
import time

# Thread approach: multiple OS threads
def thread_worker(name):
    print(f'Thread {name}: start')
    time.sleep(1)  # Blocks the thread
    print(f'Thread {name}: done')

threads = [threading.Thread(target=thread_worker, args=(i,)) for i in range(3)]
for t in threads:
    t.start()
for t in threads:
    t.join()

print('---')

# Coroutine approach: single-threaded event loop
async def coro_worker(name):
    print(f'Coro {name}: start')
    await asyncio.sleep(1)  # Suspends, does NOT block other coroutines
    print(f'Coro {name}: done')

async def main():
    await asyncio.gather(*[coro_worker(i) for i in range(3)])

asyncio.run(main())
# Both approaches run 3 tasks in ~1 second total, but coroutines use one thread

Titik Masuk asyncio.run()

asyncio.run() mencipta gelung peristiwa baharu, menjalankan korutin yang diberikan sehingga selesai dan menutup gelung tersebut. Ini ialah titik masuk standard untuk program tak segerak dalam Python 3.7+.

import asyncio

async def agent_main():
    print('Agent starting')
    # All agent async work goes here
    results = await asyncio.gather(
        asyncio.sleep(0.1),  # Simulated LLM call
        asyncio.sleep(0.1),  # Simulated DB query
    )
    print('Agent done')
    return 'complete'

# Run the agent
result = asyncio.run(agent_main())
print('Result:', result)

# WRONG: calling asyncio.run() inside an already-running event loop
# In Jupyter notebooks, use: await agent_main() directly
# Or: nest_asyncio.apply() then asyncio.run()

Kesilapan Lazim: Menyekat dalam Konteks Tak Segerak

Jangan sekali-kali memanggil fungsi yang menyekat (time.sleep, requests.get, I/O fail segerak) dalam kod tak segerak. Tindakan ini menyekat keseluruhan gelung peristiwa dan menghapuskan semua keserentakan.

import asyncio
import time
import httpx

# WRONG: blocks the event loop
async def bad_agent_step():
    time.sleep(2)          # Blocks all other coroutines
    # requests.get(url)    # Also blocks - do NOT use requests in async code
    return 'done'

# RIGHT: use async equivalents
async def good_agent_step():
    await asyncio.sleep(2)  # Suspends, other coroutines can run
    
    async with httpx.AsyncClient() as client:
        response = await client.get('https://api.example.com/data')
    return response.text

# For CPU-intensive work: use run_in_executor
import concurrent.futures

async def cpu_intensive_step(data: str):
    loop = asyncio.get_event_loop()
    with concurrent.futures.ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(pool, expensive_cpu_fn, data)
    return result

def expensive_cpu_fn(data):
    # CPU-bound work runs in separate process
    return data.upper()

print('Blocking vs non-blocking patterns demonstrated')

Terlupa await: Pepijat Senyap

Jika await terlupa, ralat tidak akan dicetuskan — sebaliknya, objek korutin dikembalikan dan bukannya hasil. Ini ialah pepijat senyap yang menyebabkan ralat susulan atau hasil kosong.

import asyncio

async def get_answer() -> str:
    await asyncio.sleep(0.1)
    return 'The answer is 42'

async def bad_call():
    result = get_answer()   # WRONG: forgot await
    print(type(result))     # <class 'coroutine'> - not a string!
    # Using result as a string here causes AttributeError or wrong behavior
    return result

async def good_call():
    result = await get_answer()  # CORRECT
    print(type(result))           # <class 'str'>
    return result

async def main():
    bad = await bad_call()
    print('Bad result:', bad)    # coroutine object, not the string
    
    good = await good_call()
    print('Good result:', good)  # 'The answer is 42'
    
    # Clean up the uncollected coroutine
    if asyncio.iscoroutine(bad):
        bad.close()

asyncio.run(main())

Masalah Gelung Peristiwa Bersarang

Memanggil asyncio.run() di dalam gelung peristiwa yang sedang berjalan (contohnya, Jupyter atau FastAPI) akan mencetuskan RuntimeError. Penyelesaiannya: gunakan await secara terus atau gunakan nest_asyncio untuk buku nota.

import asyncio

async def my_agent_coroutine():
    await asyncio.sleep(0.1)
    return 'done'

# In FastAPI or other async frameworks, the event loop is already running
# Use await directly in async endpoints:
async def fastapi_endpoint():
    # WRONG inside async context:
    # result = asyncio.run(my_agent_coroutine())  # RuntimeError!
    
    # CORRECT: just await
    result = await my_agent_coroutine()
    return result

# In Jupyter notebooks: install nest_asyncio
# import nest_asyncio
# nest_asyncio.apply()
# Then asyncio.run() works

# Detect if running in event loop:
def run_agent(coro):
    try:
        loop = asyncio.get_running_loop()
        # Already in async context
        import concurrent.futures
        with concurrent.futures.ThreadPoolExecutor() as pool:
            future = pool.submit(asyncio.run, coro)
            return future.result()
    except RuntimeError:
        # No running loop
        return asyncio.run(coro)

print('Nested event loop solution defined')

asyncio.create_task

Gunakan asyncio.create_task() untuk menjadualkan korutin supaya berjalan tanpa menunggunya dengan serta-merta. Dengan cara ini, anda boleh memulakan beberapa tugasan dan menunggu penyelesaiannya kemudian.

import asyncio

async def background_job(job_id: int) -> str:
    await asyncio.sleep(0.5)
    return f'Job {job_id} completed'

async def main():
    # Start all tasks without waiting
    task1 = asyncio.create_task(background_job(1))
    task2 = asyncio.create_task(background_job(2))
    task3 = asyncio.create_task(background_job(3))
    
    # Do other work while tasks run
    print('Tasks started, doing other work...')
    await asyncio.sleep(0.1)
    print('Other work done')
    
    # Now wait for all tasks
    results = await asyncio.gather(task1, task2, task3)
    print('All results:', results)
    
    # Or wait for the first to complete
    task_a = asyncio.create_task(background_job(4))
    task_b = asyncio.create_task(background_job(5))
    done, pending = await asyncio.wait([task_a, task_b], return_when=asyncio.FIRST_COMPLETED)
    for t in pending:
        t.cancel()  # Cancel remaining tasks
    print('First result:', done.pop().result())

asyncio.run(main())

Pengurus Konteks Tak Segerak

Banyak pustaka tak segerak menggunakan pengurus konteks tak segerak dengan async with. Ini memastikan penyediaan dan pengemasan sambungan serta sumber dilakukan dengan betul dalam kod tak segerak.

import asyncio
import httpx

async def fetch_multiple_urls(urls: list) -> list:
    # async with ensures the client is properly closed
    async with httpx.AsyncClient(timeout=10.0) as client:
        # Fetch all URLs concurrently
        tasks = [client.get(url) for url in urls]
        responses = await asyncio.gather(*tasks, return_exceptions=True)
        
        results = []
        for url, response in zip(urls, responses):
            if isinstance(response, Exception):
                results.append({'url': url, 'error': str(response)})
            else:
                results.append({'url': url, 'status': response.status_code})
        return results

# Async generators for streaming
async def stream_agent_events():
    events = ['thinking', 'searching', 'generating', 'done']
    for event in events:
        await asyncio.sleep(0.2)  # Simulate event arrival
        yield event

async def consume_stream():
    async for event in stream_agent_events():
        print(f'Event: {event}')

asyncio.run(consume_stream())

Pengendalian Ralat dalam Kod Tak Segerak

Gunakan asyncio.gather(..., return_exceptions=True) untuk menangkap kegagalan tugasan secara individu tanpa menghentikan keseluruhan kelompok. Periksa setiap hasil untuk jenis pengecualian.

import asyncio

async def might_fail(task_id: int) -> str:
    await asyncio.sleep(0.1)
    if task_id == 2:
        raise ValueError(f'Task {task_id} failed')
    return f'Task {task_id} succeeded'

async def robust_gather():
    tasks = [might_fail(i) for i in range(1, 5)]
    
    # return_exceptions=True: exceptions are returned as values, not raised
    results = await asyncio.gather(*tasks, return_exceptions=True)
    
    successes = []
    failures = []
    for i, result in enumerate(results):
        if isinstance(result, Exception):
            failures.append({'task': i + 1, 'error': str(result)})
        else:
            successes.append(result)
    
    print(f'Succeeded: {len(successes)}, Failed: {len(failures)}')
    print('Failures:', failures)
    return successes, failures

asyncio.run(robust_gather())

Semakan Pengetahuan: Python Tak Segerak

Uji pemahaman anda tentang Python tak segerak untuk pembangunan ejen.

Ringkasan Python Tak Segerak

Peraturan utama Python tak segerak untuk pembangun ejen: gunakan async def/await untuk semua operasi yang terikat I/O; jangan sekali-kali memanggil fungsi yang menyekat dalam konteks tak segerak; gunakan asyncio.gather() untuk pelaksanaan selari; gunakan return_exceptions=True untuk panggilan selari yang toleran terhadap kegagalan; gunakan async with untuk pengurusan sumber; jalankan kerja yang intensif CPU dalam pelaksana himpunan proses.

Percuma untuk bermula

Pelajari Ejen AI dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
60
Pelajaran
239

Soalan Lazim

Adakah pelajaran “Python Tak Segerak untuk Pembangun Ejen” percuma?

Ya — teks penuh “Python Tak Segerak untuk Pembangun Ejen” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Ejen AI, tingkat taraf kepada CoddyKit PRO. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Python Tak Segerak untuk Pembangun Ejen”?

Asas asyncio, async def, await, gelung peristiwa — model mental tak segerak. Anda berlatih Ejen AI menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Ejen AI?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Ejen AI di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.

Berapa lamakah pelajaran “Python Tak Segerak untuk Pembangun Ejen” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Ejen AI ini?

Ya. Setiap pelajaran Ejen AI menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Python Tak Segerak untuk Pembangun Ejen
  2. Baris Gilir Peristiwa dan Broker Mesej
  3. Pelaksanaan Alat Selari Tanpa Sekatan
  4. Rangka Kerja Ejen Tak Segerak: LangChain dan Lain-lain
← Kembali ke Ejen AI