await
Updated March 26, 2026 · Keywords
await async asyncio concurrency
Syntax
The await keyword suspends execution of an async function until the awaited awaitable is complete. It may only be used inside a function declared with async def.
await expression
```python
It is a **syntax error** to use `await` outside an `async def` body. The Python parser raises `SyntaxError: 'await' outside async function` before any code runs.
## What `await` Does
When execution reaches `await expression`, three things happen in sequence:
1. **Suspend** — the calling async function pauses at the `await` line. Local variables are preserved on the call stack.
2. **Yield control** — the event loop is free to run other scheduled tasks.
3. **Resume** — when the awaited awaitable finishes, the event loop schedules the caller to continue. The `await` expression returns the awaitable's result, or raises its exception.
This cooperative yielding is the foundation of Python's single-threaded concurrency model. No thread switching occurs — the event loop drives all async tasks on one thread.
```python
import asyncio
async def fetch():
await asyncio.sleep(1)
return 42
async def main():
result = await fetch()
print(result)
asyncio.run(main())
# output: 42
```python
In this example, `main()` suspends at `await fetch()` and yields to the event loop. When `fetch()` completes after one second, `main()` resumes and receives the value `42`.
## Awaitable Types
The operand of `await` must be an **awaitable**: any object that implements `__await__()`. Python defines three built-in awaitable types:
| Type | Created by | Notes |
|------|-----------|-------|
| Coroutine | Calling an `async def` function | Most common |
| `Task` | `asyncio.create_task()` | Scheduled on the event loop |
| `Future` | `asyncio` internals or `loop.create_future()` | Low-level, result set by callback |
### Coroutine
Every `async def` function returns a coroutine object when called. That object is awaitable:
```python
async def get_data():
return "data"
coro = get_data() # coroutine object — not yet running
result = await coro # executes get_data(), returns "data"
```python
A coroutine does nothing until it is awaited or passed to `asyncio.create_task()`.
### Task
`asyncio.Task` wraps a coroutine and schedules it on the event loop. Tasks are created implicitly by helpers like `asyncio.create_task()` and can be awaited like coroutines:
```python
async def step(n):
await asyncio.sleep(n * 0.1)
return n * 10
async def main():
task = asyncio.create_task(step(2))
result = await task # waits for this specific task
print(result)
asyncio.run(main())
# output: 20
```python
### Future
`asyncio.Future` is a low-level awaitable whose result is set asynchronously, usually by the event loop or an I/O operation. You rarely create Futures directly, but APIs like `asyncio.wait_for()` accept and wrap them:
```python
async def main():
loop = asyncio.get_running_loop()
fut = loop.create_future()
loop.call_soon(lambda: fut.set_result("done"))
result = await fut
print(result)
asyncio.run(main())
# output: done
```python
## Common Patterns
### `asyncio.create_task()`
Schedules a coroutine as a concurrent task. The call returns immediately with a `Task`, before the coroutine has run:
```python
import asyncio
async def task_a():
await asyncio.sleep(1)
return "A done"
async def task_b():
await asyncio.sleep(0.5)
return "B done"
async def main():
t1 = asyncio.create_task(task_a())
t2 = asyncio.create_task(task_b())
r1 = await t1
r2 = await t2
print(r1, r2)
asyncio.run(main())
# output: A done B done
```python
Both tasks run concurrently. `task_b()` finishes in 0.5 seconds while `task_a()` sleeps for 1 second, so `B done` prints before `A done`.
### `asyncio.gather()`
Awaits multiple awaitables concurrently and returns results as a list in input order:
```python
import asyncio
async def step(n):
await asyncio.sleep(n * 0.1)
return n * 10
async def main():
results = await asyncio.gather(step(1), step(2), step(3))
print(results)
asyncio.run(main())
# output: [10, 20, 30]
```python
`step(1)`, `step(2)`, and `step(3)` all run at the same time. After 0.3 seconds (the longest sleep), all three have completed and `gather` returns the ordered list of results.
### `asyncio.wait_for()`
Adds a timeout to any awaitable. Raises `asyncio.TimeoutError` if the deadline passes before completion:
```python
import asyncio
async def slow():
await asyncio.sleep(5)
return "finished"
async def main():
try:
result = await asyncio.wait_for(slow(), timeout=1.0)
print(result)
except asyncio.TimeoutError:
print("timed out")
asyncio.run(main())
# output: timed out
```python
`slow()` takes 5 seconds, but `wait_for()` cancels it after 1 second and raises `TimeoutError`. This pattern is essential for building responsive async applications.
### `asyncio.shield()`
Prevents a critical awaitable from being cancelled when its caller is cancelled. If the caller times out or is otherwise cancelled, `shield()` keeps the underlying task alive:
```python
import asyncio
async def critical():
await asyncio.sleep(3)
return "critical done"
async def main():
task = asyncio.create_task(critical())
try:
result = await asyncio.wait_for(asyncio.shield(task), timeout=1.0)
print(result)
except asyncio.TimeoutError:
print("shielded task still running in background")
await task # wait for it to finish properly
asyncio.run(main())
# output: shielded task still running in background
# (after ~3s): task completes
```python
`wait_for()` times out after 1 second, but `asyncio.shield(task)` prevents the cancellation from propagating to `critical()`. The caller reports the timeout while the critical task continues running in the background.
## SyntaxError: `await` Outside `async def`
Using `await` outside an `async def` body is a hard syntax error. The Python parser rejects it at parse time — no execution possible.
```python
# Module level — SyntaxError
await asyncio.sleep(1)
# SyntaxError: 'await' outside async function
```python
```python
# Inside a regular function — SyntaxError
def blocking():
await asyncio.sleep(1)
# SyntaxError: 'await' outside async function
```python
```python
# Inside a lambda — SyntaxError
f = lambda: await asyncio.sleep(1)
# SyntaxError: 'await' outside async function
```python
The only valid contexts for `await` are:
- Inside the body of an `async def` function
- Inside a coroutine or async generator body
## See Also
- [`async` keyword](/reference/keywords/async-keyword/) — defines async functions and generators
- [`asyncio` module](/reference/modules/asyncio-module/) — `create_task()`, `gather()`, `wait_for()`, `shield()`