Skip to content
Aabha AI Academy

Module 5 of 9 · Lesson 12 of 26

See how awaited I/O changes scheduling

Work through see how awaited I/O changes scheduling using a runnable reference, a focused regression check and a local extension.

Read in any order. All lessons stay open, including after an unanswered or incorrect check.

In this lesson you will see how awaited I/O changes scheduling. Work with the Equipment Rental API in the downloadable lab. The reference is a complete solution with separate lesson checks, so you can inspect the answer, make a deliberate local change and verify its behavior.
Awaited I/O gives the event loop an opportunity to run another coroutine while the first waits. It does not make arbitrary Python work parallel. In the scheduling example, one task waits on an asyncio.Event; another records work and releases it. The observed order shows that the waiting task resumes only after the event is set.

Use async def when the called libraries expose awaitable I/O. A blocking database client or time.sleep inside async def still blocks the event-loop thread. An ordinary synchronous FastAPI route can be appropriate for synchronous libraries; changing def to async def without changing the I/O is not an improvement. CPU-heavy password hashing is offloaded in lesson 15. asyncio.gather schedules independent coroutines, but their resources must also be independent. This lesson uses event ordering rather than a wall-clock speed claim because noisy machines make tiny timing benchmarks misleading. The useful question is whether other work can proceed during the wait and whether cancellation and ownership remain clear.
Worked source: tests/test_lessons.py, test_lesson12.

Run lesson12 and read its gate.wait, sleep(0), gate.set and final assertion. The expected sequence is waiting, other-work, resumed. sleep(0) yields control without simulating provider latency. Compare this deterministic order with calling a blocking sleep inside the event-loop thread.
pythonCopyable
@pytest.mark.asyncio
async def test_lesson12():
    events = []
    gate = asyncio.Event()

    async def waiting():
        events.append("waiting")
        await gate.wait()
        events.append("resumed")

    task = asyncio.create_task(waiting())
    await asyncio.sleep(0)
    events.append("other-work")
    gate.set()
    await task
    assert events == ["waiting", "other-work", "resumed"]
TerminalPython 3.13 virtual environment; Docker running; extracted lab directory
python run_checks.py -k lesson12

Expected result The selected lesson test passes against a new temporary PostgreSQL database; the container is removed afterward.

Keep for reference

Equipment Rental lab and lesson checks

ZIP containing Python source, real Alembic migrations, 26 lesson checks, a dependency lock and text instructions. Extract it before following the local exercise.

Download Equipment Rental lab and lesson checks

Practise locally

Write two coroutines that each announce arrival and wait on the same event. Start both, assert both arrived before releasing the event, then await their results. Add a cancellation case that cancels one waiting task and confirms the other still resumes. Avoid using a fast-machine timing threshold as the only evidence.

The lesson check verifies the reference behavior. Add your own assertions for your change. Local practice is not uploaded or scored by this learning release.

Pause and reflect

What failure does this lesson prevent, and which assertion in lesson12 would expose it?

Use a concrete input, expected result and limitation from your local work. Saving a reflection does not certify the project.

Optional knowledge check

What does await on a genuine I/O operation allow?

Await a synchronous blocking call and it becomes asynchronous.

Try another answer. The library must expose awaitable I/O or be deliberately offloaded.

Other coroutines can run while this operation waits.

Correct. The event loop can schedule other ready work until the awaited operation is ready.

Any blocking call inside async def automatically becomes nonblocking.

Try another answer. Blocking libraries and CPU work still occupy the event-loop thread unless deliberately handled.

This practice does not assess your project or award a certificate.

Your reading progress

Progress is saved in this browser when storage is available.

Sign in to save across devices · Create an optional account