Skip to content
Back to skills

Async Await Checker

ASecurity

Automatically applies when writing Python functions that call async operations. Ensures proper async/await pattern usage (not asyncio.run) to prevent event loop errors.

  • 57 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 31, 2026
developmentpythonfastapitestingapidatabaseperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned May 31, 2026

npx -y skills add diegosouzapw/awesome-omni-skill --skill async-await-checker --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Async Await Checker?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Async Await Checker
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/diegosouzapw-async-await-checker/badge)](https://www.skillsdirectory.com/skills/diegosouzapw-async-await-checker)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: async-await-checker
description: Automatically applies when writing Python functions that call async operations. Ensures proper async/await pattern usage (not asyncio.run) to prevent event loop errors.
---

# Async/Await Pattern Enforcer

When you are writing or modifying Python functions that:
- Call any function with `async def`
- Work with async I/O operations (database, HTTP, file I/O)
- Need to run in an async context (FastAPI, async frameworks)

**Always apply these patterns:**

## ✅ Correct Pattern

```python
# Helper function
async def fetch_user_data(user_id: str) -> dict:
    """Fetch user data from database."""
    result = await db.query(user_id)  # ✅ Use await
    return result

# API endpoint (FastAPI)
@app.get("/users/{user_id}")
async def get_user(user_id: str) -> dict:  # ✅ async def
    data = await fetch_user_data(user_id)  # ✅ await
    return data

# Multiple async calls
async def process_order(order_id: str) -> dict:
    # ✅ Run sequentially
    user = await fetch_user(order_id)
    payment = await process_payment(user.id)

    # ✅ Run in parallel with asyncio.gather
    results = await asyncio.gather(
        send_email(user.email),
        update_inventory(order_id),
        log_transaction(payment.id)
    )

    return {"status": "success"}
```

## ❌ Incorrect Pattern (Causes Runtime Errors)

```python
# ❌ Don't do this
def fetch_user_data(user_id: str):
    result = asyncio.run(db.query(user_id))  # ❌ asyncio.run in event loop = error!
    return result

# ❌ Missing async
@app.get("/users/{user_id}")
def get_user(user_id: str):  # ❌ Should be async def
    data = fetch_user_data(user_id)  # ❌ Not awaiting
    return data

# ❌ Blocking in async function
async def process_order(order_id: str):
    time.sleep(5)  # ❌ Blocks event loop! Use asyncio.sleep(5)
    return await fetch_data()
```

## Why This Matters

**Runtime Error:** `asyncio.run()` fails when called from within an already-running event loop.

**Solution:** Always use `async def` + `await` pattern.

**Performance:** Blocking operations in async functions defeat the purpose of async code.

## Common Async Operations

**Database queries:**
```python
async def get_records():
    async with db.session() as session:
        result = await session.execute(query)
        return result.fetchall()
```

**HTTP requests:**
```python
import httpx

async def fetch_api_data(url: str):
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        return response.json()
```

**File I/O:**
```python
import aiofiles

async def read_file(path: str):
    async with aiofiles.open(path, 'r') as f:
        content = await f.read()
        return content
```

## Error Handling in Async

```python
async def safe_api_call(url: str):
    try:
        async with httpx.AsyncClient() as client:
            response = await client.get(url, timeout=10.0)
            response.raise_for_status()
            return response.json()
    except httpx.TimeoutException:
        raise TimeoutError(f"Request to {url} timed out")
    except httpx.HTTPStatusError as e:
        raise APIError(f"API error: {e.response.status_code}")
```

## Testing Async Code

```python
import pytest

@pytest.mark.asyncio
async def test_fetch_user_data():
    """Test async function"""
    result = await fetch_user_data("user_123")
    assert result["id"] == "user_123"

@pytest.mark.asyncio
async def test_with_mock():
    """Test with mocked async dependency"""
    with patch('module.db.query') as mock_query:
        mock_query.return_value = {"id": "test"}
        result = await fetch_user_data("test")
        assert result["id"] == "test"
```

## ❌ Anti-Patterns

```python
# ❌ Mixing sync and async incorrectly
def sync_function():
    return asyncio.run(async_function())  # Only OK at top level!

# ❌ Not using asyncio.gather for parallel operations
async def slow_version():
    result1 = await operation1()  # Waits
    result2 = await operation2()  # Waits
    result3 = await operation3()  # Waits
    return [result1, result2, result3]

# ✅ Better: parallel execution
async def fast_version():
    results = await asyncio.gather(
        operation1(),
        operation2(),
        operation3()
    )
    return results

# ❌ Forgetting error handling in gather
async def unsafe():
    await asyncio.gather(op1(), op2())  # If op1 fails, op2 continues

# ✅ Better: return exceptions
async def safe():
    results = await asyncio.gather(
        op1(), op2(),
        return_exceptions=True
    )
    for result in results:
        if isinstance(result, Exception):
            handle_error(result)
```

## Best Practices Checklist

- ✅ Use `async def` for any function that awaits
- ✅ Use `await` for all async calls
- ✅ Use `asyncio.gather()` for parallel operations
- ✅ Use `async with` for async context managers
- ✅ Use `asyncio.sleep()` instead of `time.sleep()`
- ✅ Add proper error handling with try/except
- ✅ Use `@pytest.mark.asyncio` for async tests
- ✅ Consider timeouts for external operations
- ✅ Use `return_exceptions=True` in gather when appropriate

## Auto-Apply

When you see code calling async functions, automatically:
1. Make the calling function `async def`
2. Use `await` for async calls
3. Update callers to also be async (chain up)
4. Add `@pytest.mark.asyncio` to tests
5. Replace blocking calls with async equivalents

## Related Skills

- pytest-patterns - For testing async code
- structured-errors - For async error handling
- tool-design-pattern - For async tools

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.