Python Asynchronous Programming Sinhala Tutorial | asyncio Basics SC Guide

Python Asynchronous Programming Sinhala Tutorial | asyncio Basics SC Guide

Python Async Programming: `asyncio` Basics – Asynchronous Programming වලට අත තබමු!

ඉතින් කොහොමද යාලුවනේ! ඔයාලා Software Engineering කරන අය නම්, නැත්නම් Python වලින් Applications හදනවා නම්, මේ කියන දේ ගොඩක් වැදගත් වෙයි. අද අපි කතා කරන්න යන්නේ Python වල තියෙන සුපිරිම feature එකක් ගැන – ඒ තමයි Asynchronous Programming, විශේෂයෙන්ම asyncio module එක ගැන. හරිද?

අපි හිතමු ඔයාලා Web Application එකක් හදනවා කියලා. ඒකේ User කෙනෙක් Button එකක් Click කලාම, ඒ වෙලාවෙම Backend එකට Request එකක් යනවා, Database එකෙන් Data ටිකක් ගන්න. ඊට පස්සේ, ඒ Data ටික Process කරලා, ආපහු User ට පෙන්නනවා. මේ වගේ වෙලාවක, එකම වෙලාවෙදී ගොඩක් Users ලා Application එක පාවිච්චි කරනවා නම්, Program එකේ Speed එක අඩුවෙන්න පුළුවන්. මොකද, හැම request එකක්ම එකින් එකට (sequentially) execute වෙන්න බලන් ඉන්න නිසා.

මෙන්න මේ වගේ වෙලාවට තමයි Asynchronous Programming අපිට ගොඩක් උදව් වෙන්නේ. Asynchronous Programming කියන්නේ අපේ Program එකට එකම වෙලාවෙදී Task කීපයක් handle කරන්න පුළුවන් වෙන විදියක්. විශේෂයෙන්ම, Network Requests, Database Queries, File I/O වගේ, Program එකේ Main Execution එකට බලපාන්නේ නැතුව, වෙනම background එකේ කරගන්න පුළුවන් දේවල් වලදී මේක ගොඩක් ප්‍රයෝජනවත්.

මේ Guide එකෙන් අපි `asyncio` කියන්නේ මොකක්ද, ඒකේ මූලිකාංග මොනවද, සරලව `asyncio` Program එකක් ලියන්නේ කොහොමද වගේ දේවල් ගැන සරලව කතා කරමු. ඒ වගේම, `asyncio` use කරනකොට මතක තියාගන්න ඕන දේවල් සහ Best Practices ටිකකුත් බලමු. එහෙනම්, අපි පටන් ගමු!

Asynchronous Programming කියන්නේ මොකක්ද? (What is Asynchronous Programming?)

සරලවම කිව්වොත්, Asynchronous Programming කියන්නේ Program එකකට Task එකක් ඉවර වෙනකන්ම බලන් ඉන්නේ නැතුව, වෙන Task එකකට මාරු වෙලා ඒක කරගෙන ඉන්න පුළුවන් විදියක්. හරියට Restaurant එකක Waiter කෙනෙක් වගේ. Waiter කෙනෙක් Order එකක් අරන් Kitchen එකට දුන්නාම, ඒ Order එක හදනකම් එතනම ඉන්නේ නැතුව, තව Customer කෙනෙක්ගේ Order එකක් ගන්න යනවා, නැත්නම් Drinks ගෙනත් දෙනවා. අර පළවෙනි Order එක Ready වුනාම ආපහු ඇවිත් ඒක Serve කරනවා.

මේකට සාපේක්ෂව, Synchronous Programming කියන්නේ, Program එක Task එකක් ඉවර කරනකම්ම බලන් ඉඳලා, ඒක ඉවර වුනාම ඊලඟ Task එකට යන එක. ඒ කියන්නේ, එක Task එකක් Run වෙන වෙලාවේදී වෙන කිසිම Task එකක් Run වෙන්නේ නෑ. මේක පොඩි Programs වලට ගැටලුවක් නැතත්, Network එකත් එක්ක වැඩ කරන, ගොඩක් I/O Operations තියෙන Programs වලදී Performance එකට ලොකු බලපෑමක් කරනවා.

Python වලට `asyncio` කියන Module එකත් එක්ක Asynchronous Programming කරන්න පුළුවන්කම ලැබුනේ Python 3.4 එක්ක. හැබැයි, ඒක ජනප්‍රිය වුනේ async සහ await Keywords ආවට පස්සේ, Python 3.5 වලින් පස්සේ තමයි.

`asyncio` වල මූලිකාංග: Event Loop, Coroutines, `async` සහ `await`

හරි, `asyncio` වැඩ කරන විදිය තේරුම් ගන්න මේ Concepts ටික දැනගෙන ඉන්න එක අත්‍යාවශ්‍යයි.

1. Event Loop

Event Loop කියන්නේ `asyncio` Program එකක හදවත වගේ දෙයක්. හරියට Orchestra එකක Conductor කෙනෙක් වගේ. ඒක කරන්නේ, මේ Program එකේ තියෙන `async` Tasks ඔක්කොම Organize කරන එක. මොන Task එකද දැන් Run වෙන්න ඕන, මොන Task එකද Pause වෙන්න ඕන, මොන Task එකද ඊළඟට Start වෙන්න ඕන වගේ දේවල් manage කරන්නේ Event Loop එකෙන්. අපි Code එකක් ලියනකොට අපිට කෙලින්ම Event Loop එකත් එක්ක වැඩ කරන්න අවශ්‍ය වෙන්නේ නෑ, මොකද asyncio.run() වගේ Functions වලින් ඒක automate වෙනවා.

2. Coroutines (`async def`)

Coroutines කියන්නේ Asynchronous Functions වලට. මේවා සාමාන්‍ය Functions වගේම තමයි. හැබැයි, මේවායේ async def කියන Keyword එක පාවිච්චි කරනවා. Coroutines වලට පුළුවන් තාවකාලිකව Pause වෙලා, පස්සේ ඒ නැවතුන තැන ඉඳන් ආපහු පටන් ගන්න. මේ හැකියාව නිසා තමයි අපිට Asynchronous Programming කරන්න පුළුවන් වෙන්නේ. await Keyword එකක් හම්බුනාම Coroutine එක Pause වෙනවා, ඊට පස්සේ Event Loop එක වෙන Task එකකට යනවා.

async def my_async_function():
    print("Hello from async function!")
    await asyncio.sleep(1) # Simulate some I/O operation
    print("Async function finished!")

මතක තියාගන්න, async def වලින් Define කරපු Function එකක් Call කරාට, ඒක ඒ වෙලාවෙම Run වෙන්නේ නෑ. ඒක Coroutine Object එකක් Return කරනවා. ඒ Object එක Event Loop එකට දීලා Run කරන්න ඕන.

3. `async` සහ `await` Keywords

  • `async`: මේ Keyword එකෙන් කියන්නේ මේ Function එක Coroutine එකක් කියලා. ඒ කියන්නේ මේක Asynchronous විදියට Run වෙන්න පුළුවන් කියලා.
  • `await`: මේ Keyword එක ගොඩක්ම වැදගත්. await කියලා ලියන්නේ Asynchronous Operation එකක් ඉවර වෙනකම් බලන් ඉන්න ඕන තැනකදී. අපි await කරාම, Coroutine එක Pause වෙනවා, Event Loop එකට පුළුවන් මේ අතරතුර වෙන Task එකක් Run කරන්න. අර await කරපු Operation එක ඉවර වුනාම (උදාහරණයක් විදියට Network Request එකක් ආවම), Event Loop එක ආපහු අපේ Coroutine එකට ඇවිත් නැවතුන තැන ඉඳන් Run කරන්න පටන් ගන්නවා.

await කරන්න පුළුවන් Coroutines, Futures, සහ Tasks වගේ awaitable objects විතරයි.

සරල `asyncio` උදාහරණ (Simple `asyncio` Examples)

හරි, දැන් අපි `asyncio` වලින් සරල Program දෙකක් බලමු.

1. “Hello, World!” `async` Program එකක්

මුලින්ම, `asyncio` වලින් කොහොමද සරලම Program එකක් Run කරන්නේ කියලා බලමු. මේකේදී අපි asyncio.sleep() කියන Function එක පාවිච්චි කරනවා, මොකද මේක await කරන්න පුළුවන් Asynchronous Operation එකක් Simulate කරන්න හොඳම විදියක්.

import asyncio

async def hello_world():
    print("Hello,")
    await asyncio.sleep(1) # තත්පර 1ක් Program එක Pause කරනවා (blocking නෙවෙයි)
    print("World!")

# Program එක Run කරන්න Main Entry Point එක
if __name__ == "__main__":
    print("Starting Async Hello World...")
    asyncio.run(hello_world()) # hello_world() coroutine එක Event Loop එකේ Run කරනවා
    print("Async Hello World Finished!")

මේ Code එක Run කලාම, output එක මෙහෙම එයි:

Starting Async Hello World...
Hello,
(තත්පර 1කකට පස්සේ)
World!
Async Hello World Finished!

මෙහිදී asyncio.sleep(1) කියන්නේ Program එකේ Main Thread එක Block කරන්නේ නැතුව, Event Loop එකට පුළුවන් වෙන Task එකකට මාරු වෙන්න කියලා කියන එකක්. සාමාන්‍ය time.sleep(1) වගේ නෙවෙයි.

2. එකම වෙලාවෙදී Coroutines කිහිපයක් Run කිරීම (Running Concurrent Coroutines)

දැන් අපි බලමු කොහොමද Coroutines කීපයක් එකම වෙලාවෙදී Run කරලා, ඒකෙන් කොහොමද Time Save වෙන්නේ කියලා. මේක කරන්න අපි asyncio.gather() කියන Function එක පාවිච්චි කරනවා.

import asyncio
import time

async def worker_task(task_id, delay):
    print(f"Task {task_id}: Starting. Will work for {delay} seconds.")
    await asyncio.sleep(delay) # simulate work / I/O
    print(f"Task {task_id}: Finished after {delay} seconds.")
    return f"Task {task_id} completed!"

async def main_concurrent_example():
    start_time = time.perf_counter()

    # Coroutines 3ක් එකම වෙලාවෙදී Run කරන්න සූදානම් කරනවා
    results = await asyncio.gather(
        worker_task("A", 3), # තත්පර 3ක් ගන්නවා
        worker_task("B", 1), # තත්පර 1ක් ගන්නවා
        worker_task("C", 2)  # තත්පර 2ක් ගන්නවා
    )

    end_time = time.perf_counter()
    print(f"\nAll tasks completed in {end_time - start_time:.2f} seconds.")
    print(f"Results: {results}")

if __name__ == "__main__":
    print("Starting Concurrent Example...")
    asyncio.run(main_concurrent_example())
    print("Concurrent Example Finished!")

මේ Code එක Run කලාම ඔයාලට පෙනෙයි, Tasks තුනම එකම වෙලාවෙදී පටන් ගන්නවා. සම්පූර්ණ Program එක ඉවර වෙන්නේ වැඩිම කාලයක් ගන්න Task එකේ (මේ Example එකේදී Task A, තත්පර 3ක්) කාලයට විතරයි. සාමාන්‍ය Synchronous Program එකක මේ Tasks තුනම එකින් එකට Run කලා නම්, තත්පර 3 + 1 + 2 = 6 ක් විතර වෙලාවක් යනවා.

Starting Concurrent Example...
Task A: Starting. Will work for 3 seconds.
Task B: Starting. Will work for 1 seconds.
Task C: Starting. Will work for 2 seconds.
Task B: Finished after 1 seconds.
Task C: Finished after 2 seconds.
Task A: Finished after 3 seconds.

All tasks completed in 3.00 seconds.
Results: ['Task A completed!', 'Task B completed!', 'Task C completed!']
Concurrent Example Finished!

පෙනවනේ, අපිට තත්පර 3න් Tasks තුනම ඉවර කරගන්න පුළුවන් වුනා. මේක තමයි Asynchronous Programming වල ලොකුම වාසියක්!

Blocking Operations සහ Debugging

Blocking Operations

asyncio Program එකකදී වැදගත්ම දේ තමයි, Event Loop එක Block නොවී තියාගන්න එක. Event Loop එක Block වුනොත්, අපේ Program එකට එකම වෙලාවෙදී Task කීපයක් handle කරන්න තියෙන හැකියාව නැති වෙනවා. ඒ කියන්නේ, Async Program එකක් වුනත්, Synchronous Program එකක් වගේ හැසිරෙන්න පුළුවන්.

Event Loop එක Block කරන ප්‍රධාන දේ තමයි CPU-bound operations. ඒ කියන්නේ, ගණන් හැදීම්, Data Process කිරීම් වගේ CPU එකට බර වැඩ. ඒ වගේම time.sleep() වගේ Synchronous Blocking Calls. ඒ වෙනුවට, asyncio.sleep() වගේ `asyncio` friendly Functions පාවිච්චි කරන්න ඕන.

ඔයාලට CPU-bound task එකක් Asynchronous Program එකක Run කරන්න ඕන නම්, asyncio.to_thread() (Python 3.9+) නැත්නම් loop.run_in_executor() පාවිච්චි කරන්න පුළුවන්. මේවායින් කරන්නේ, ඒ බර වැඩේ වෙනම Thread එකක නැත්නම් Process එකක Run කරලා, Main Event Loop එක Block නොවී තියාගන්න එක.

import asyncio
import time

async def cpu_intensive_task():
    print("CPU Intensive Task: Starting heavy calculation...")
    # Don't do this in an async function directly! It blocks the event loop.
    # time.sleep(5) # This is BAD for asyncio

    # Instead, run in a separate thread:
    await asyncio.to_thread(time.sleep, 5) # Python 3.9+
    # Or for older versions / more control:
    # loop = asyncio.get_running_loop()
    # await loop.run_in_executor(None, time.sleep, 5)

    print("CPU Intensive Task: Calculation finished.")

async def light_task(name):
    print(f"Light Task {name}: Starting.")
    await asyncio.sleep(0.5)
    print(f"Light Task {name}: Finished.")

async def main_blocking_example():
    await asyncio.gather(
        cpu_intensive_task(),
        light_task("X"),
        light_task("Y")
    )

if __name__ == "__main__":
    print("Starting Blocking Example...")
    asyncio.run(main_blocking_example())
    print("Blocking Example Finished!")

මේ Code එකේදී, cpu_intensive_task එකෙන් asyncio.to_thread() (නැත්නම් run_in_executor()) පාවිච්චි කරන නිසා, light_task දෙක ඒ අතරතුරදී කිසිම ගැටලුවක් නැතුව Run වෙනවා. time.sleep(5) කෙලින්ම async def එකක දැම්මා නම්, අනිත් Tasks වලටත් තත්පර 5ක් බලන් ඉන්න වෙනවා.

Debugging Async Code

Async Code Debug කරන එක සමහර වෙලාවට පොඩ්ඩක් සංකීර්ණ වෙන්න පුළුවන්, මොකද Execution Flow එක Synchronous Code එකක වගේ කෙලින්ම යන්නේ නැති නිසා. Debugging වලට මේ Tips ටික ප්‍රයෝජනවත් වෙයි:

  • print() Statements: මේවා තමයි සරලම සහ ප්‍රබලම Debugging Tool එක. Task එකක Start එකේදී සහ End එකේදී `print` Statements දාලා Task එකේ Flow එක තේරුම් ගන්න පුළුවන්.
  • Python Debugger (`pdb`): pdb වගේ Debugger එකක් use කරනවා නම්, await කරන තැන් වල pdb.set_trace() දාලා Step by Step Execution බලන්න පුළුවන්.
  • Verbose Logging: asyncio වලට තියෙනවා Built-in Logging System එකක්. logging module එක use කරලා, Event Loop එකේ වෙන දේවල් Log කරන්න පුළුවන්.
  • `asyncio` Debug Mode: asyncio.run() function එකට debug=True කියන Parameter එක දුන්නොත්, `asyncio` එකෙන් Automatic Debugging information ගොඩක් Console එකට Print කරනවා. (e.g., asyncio.run(main(), debug=True))

`asyncio` භාවිතයේදී මතක තියාගත යුතු දේවල් (Best Practices for using `asyncio`)

  • I/O-bound Applications වලට ප්‍රමුඛත්වය දෙන්න: asyncio ගොඩක්ම Design කරලා තියෙන්නේ Network Requests (APIs, Web Servers), Database Interactions, File Operations වගේ I/O-bound Operations වලදී Performance වැඩි කරන්න. CPU-bound Operations වලට asyncio එච්චරම සුදුසු නැහැ.
  • `await` කරන්න අමතක කරන්න එපා: Coroutine එකක් Call කරලා, ඒක await කරන්න අමතක වුනොත්, ඒ Coroutine එක Event Loop එකට Add වෙන්නේ නෑ. ඒක නිසා ඒක Run වෙන්නේ නෑ.
  • External Libraries වලට අවධානය: External Libraries පාවිච්චි කරනකොට, ඒගොල්ලෝ Asynchronous Operations Support කරනවද කියලා බලන්න. (උදා: httpx for HTTP requests, asyncpg for PostgreSQL). සාමාන්‍ය Blocking Libraries asyncio.to_thread() වගේ ක්‍රම වලින් Run කරන්න පුළුවන්.
  • Error Handling: asyncio Tasks වල Errors manage කරන්න try...except Blocks පාවිච්චි කරන්න. asyncio.gather() වලදී Error එකක් ආවොත්, ඒක හැම Coroutine එකකටම බලපාන්න පුළුවන්, ඒ නිසා Error Handling වැදගත්.
  • Graceful Shutdown: Server එකක් වගේ දෙයක් හදනවා නම්, Program එක Shut Down කරනකොට Running Tasks ටිකත් Gracefully Close කරන විදියක් හදන්න.

සාරාංශය සහ ඉදිරි ගමන (Conclusion and Next Steps)

අද අපි Python `asyncio` වල මූලිකාංග ගොඩක් දුරට cover කලා. Asynchronous Programming කියන්නේ මොකක්ද, Event Loop, Coroutines, async සහ await Keywords වල වැදගත්කම, සරල Examples දෙකක්, ඒ වගේම Blocking Operations සහ Debugging ගැනත් සාකච්ඡා කලා. දැන් ඔයාලට පුළුවන් මේ දැනුමෙන් Python වල වේගවත් සහ Scalable Applications හදන්න පටන් ගන්න.

`asyncio` කියන්නේ පොඩි කාලයකින් ඉගෙන ගන්න පුළුවන් Module එකක් නෙවෙයි. ඒකෙන් පුළුවන් දේවල් ගොඩක් තියෙනවා, ඒක නිසා තවදුරටත් මේ ගැන ඉගෙන ගන්න උත්සාහ කරන්න.

  • Try it out: මේ Code Examples ටික ඔයාගේ Computer එකේ Run කරලා බලන්න. වෙනස්කම් කරලා බලන්න.
  • Official Documentation: Python `asyncio` Official Documentation එක කියවන්න. ඒකෙන් තවත් ගැඹුරට විස්තර දැනගන්න පුළුවන්.
  • Build a small project: සරල Web Scraper එකක් නැත්නම් සරල Network Client එකක් වගේ දෙයක් `asyncio` වලින් හදලා බලන්න.

මේ Article එක ඔයාලට ප්‍රයෝජනවත් වෙන්න ඇති කියලා හිතනවා. ඔයාලගේ අත්දැකීම්, ප්‍රශ්න හෝ අදහස් පහලින් Comment section එකේ දාන්න. අපි ඒ ගැන කතා කරමු! නැවත හමුවෙමු!