How to Bind and Mock structlog Context in Python

Shows how to bind persistent key-value context to a structlog logger, unbind keys, and mock the logger in tests to verify context is passed correctly.

Medium Python 3.9+ Aug 9, 2026 Modern tooling 17 views 0 copies

Requires third-party packages — install first
pip install structlog

Python code

26 lines
Python 3.9+
import structlog
from unittest.mock import patch

logger = structlog.get_logger()

def demo():
    logger = structlog.get_logger()
    logger = logger.bind(user_id=42, request_id="abc123")
    logger.info("user logged in", action="login")
    
    # Unbind a key
    logger = logger.unbind("user_id")
    logger.info("request processed", status=200)
    
    # Bind with a mock context
    with patch.object(type(logger), "info") as mock_info:
        logger.info("mocked log", extra="data")
        mock_info.assert_called_once_with(
            "mocked log",
            request_id="abc123",
            extra="data",
        )
        print("Mock called with:", mock_info.call_args)

if __name__ == "__main__":
    demo()

Output

stdout
2025-01-01 12:00:00 [info] user logged in (user_id=42 request_id=abc123 action=login)
2025-01-01 12:00:00 [info] request processed (request_id=abc123 status=200)
Mock called with: call('mocked log', request_id='abc123', extra='data')

How it works

The logger.bind() method returns a new logger with persistent context added to every subsequent log call. unbind() removes a specific key without mutating the original logger. Using patch.object(type(logger), "info") patches the method at the class level so assertions can verify both the message and bound context. The mock context carries all active key-value pairs, making it easy to test that context flows through to the log call.

Common mistakes

  • Forgetting that bind returns a new logger — the original stays unchanged.
  • Patching an instance method with `patch.object(logger, "info")` instead of the class type.
  • Assuming bound context is visible inside the mock without checking call_args.

Variations

  1. Use `logger.new(user_id=42)` to bind context with a fresh log event.
  2. Use `structlog.testing.LogCapture()` to capture and inspect all log records instead of mocking.

Real-world use cases

  • Adding request-scoped metadata (user ID, trace ID) to logs in a web framework middleware.
  • Verifying structured logging output in unit tests without writing to the real log sink.
  • Removing sensitive fields (like auth tokens) from log context before the request finishes.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Modern tooling

Related tutorials and quizzes for this topic.