Generated banner for Azure Eventhub Py
Generated logo for Azure Eventhub Py

Azure Eventhub Py

MicrosoftOfficialCreated by Microsoft

  • Skill
  • Tool integration
  • Cloud and DevOps
  • MIT
  • Low risk
  • Has scripts

From the author

Azure Event Hubs SDK for Python streaming. Use for high-throughput event ingestion, producers, consumers, and checkpointing. Triggers: "event hubs", "EventHubProducerClient", "EventHubConsumerClient", "streaming", "partitions".
— the description by Microsoft

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The azure-eventhub-py skill provides the Python SDK for Azure Event Hubs. It enables developers to build producers and consumers for event streaming, manage partitions, and implement checkpointing using Azure Blob Storage. The skill includes guidance on authentication using DefaultAzureCredential, managing client lifecycles with context managers, and strategies for handling event batches and partition distribution.

What it does

  • Provides clients for producing and consuming events from Azure Event Hubs
  • Supports both synchronous and asynchronous programming models
  • Enables checkpointing of consumer progress using Azure Blob Storage
  • Facilitates partition management including direct, key-based, and round-robin routing
  • Offers methods to retrieve Event Hub and partition metadata
  • Integrates with Azure Identity for secure authentication

When to use it

  • When integrating Python applications with Azure Event Hubs
  • When building event-driven architectures requiring high-throughput ingestion
  • When implementing reliable consumer patterns with stateful checkpointing
  • When needing to distribute event processing across multiple consumers

Advantages

  • Supports consistent authentication patterns across local and cloud environments
  • Provides flexible partition selection strategies for ordered or distributed delivery
  • Includes built-in support for checkpointing to track processing progress
  • Offers consistent API design for both sync and async operations

Usage examples

“How do I send events to an Azure Event Hub using Python?”
The agent provides a code example using EventHubProducerClient, demonstrating how to create a batch, add events, and send them to the hub.
“How can I implement a consumer that tracks progress with a checkpoint store?”
The agent provides a code snippet using EventHubConsumerClient configured with a BlobCheckpointStore to update checkpoints after processing events.
“How do I route events to a specific partition in Event Hubs?”
The agent explains how to use partition_id or partition_key within the create_batch method to control event distribution.
“What is the recommended way to authenticate with Azure Event Hubs?”
The agent explains the use of DefaultAzureCredential to handle authentication across local development and production environments.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/microsoft/azure-eventhub-py/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip azure-eventhub-py.zip -d .agents/skills

Documentation by Microsoft

Azure Event Hubs SDK for Python

Big data streaming platform for high-throughput event ingestion.

Installation

pip install azure-eventhub azure-identity
# For checkpointing with blob storage
pip install azure-eventhub-checkpointstoreblob-aio

Environment Variables

EVENT_HUB_FULLY_QUALIFIED_NAMESPACE=<namespace>.servicebus.windows.net  # Required for all auth methods
EVENT_HUB_NAME=my-eventhub  # Required for all auth methods
STORAGE_ACCOUNT_URL=https://<account>.blob.core.windows.net  # Required for checkpoint storage
CHECKPOINT_CONTAINER=checkpoints  # Required for checkpoint storage
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production

Authentication & Lifecycle

🔑 Two rules apply to every code sample below:

  1. Prefer DefaultAzureCredential. It works locally (Azure CLI / VS Code / Developer CLI) and in Azure (managed identity, workload identity) with no code change. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.

    • Local dev: DefaultAzureCredential works as-is.

    • Production: set AZURE_TOKEN_CREDENTIALS=prod (or AZURE_TOKEN_CREDENTIALS=<specific_credential>) to constrain the credential chain to production-safe credentials.

  2. Wrap every client in a context manager so HTTP transports, sockets, and token caches are released deterministically:

    • Sync: with <Client>(...) as client:

    • Async: async with <Client>(...) as client: and async with DefaultAzureCredential() as credential: (from azure.identity.aio)

Snippets may abbreviate this setup, but production code should always follow both rules.

from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
from azure.eventhub import EventHubProducerClient, EventHubConsumerClient

# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
credential = DefaultAzureCredential(require_envvar=True)
# Or use a specific credential directly in production:
# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
# credential = ManagedIdentityCredential()
namespace = "<namespace>.servicebus.windows.net"
eventhub_name = "my-eventhub"

# Producer
with EventHubProducerClient(
    fully_qualified_namespace=namespace,
    eventhub_name=eventhub_name,
    credential=credential
) as producer:
    # Use producer here (see following sections for operations)
    ...

# Consumer
with EventHubConsumerClient(
    fully_qualified_namespace=namespace,
    eventhub_name=eventhub_name,
    consumer_group="$Default",
    credential=credential
) as consumer:
    # Use consumer here (see following sections for operations)
    ...

Client Types

ClientPurpose
EventHubProducerClientSend events to Event Hub
EventHubConsumerClientReceive events from Event Hub
BlobCheckpointStoreTrack consumer progress

Send Events

from azure.eventhub import EventHubProducerClient, EventData
from azure.identity import DefaultAzureCredential

with EventHubProducerClient(
    fully_qualified_namespace="<namespace>.servicebus.windows.net",
    eventhub_name="my-eventhub",
    credential=DefaultAzureCredential()
) as producer:
    # Create batch (handles size limits)
    event_data_batch = producer.create_batch()
    
    for i in range(10):
        try:
            event_data_batch.add(EventData(f"Event {i}"))
        except ValueError:
            # Batch is full, send and create new one
            producer.send_batch(event_data_batch)
            event_data_batch = producer.create_batch()
            event_data_batch.add(EventData(f"Event {i}"))
    
    # Send remaining
    producer.send_batch(event_data_batch)
Send to Specific Partition
# By partition ID
event_data_batch = producer.create_batch(partition_id="0")

# By partition key (consistent hashing)
event_data_batch = producer.create_batch(partition_key="user-123")

Receive Events

Simple Receive
from azure.eventhub import EventHubConsumerClient

def on_event(partition_context, event):
    print(f"Partition: {partition_context.partition_id}")
    print(f"Data: {event.body_as_str()}")
    partition_context.update_checkpoint(event)

with EventHubConsumerClient(
    fully_qualified_namespace="<namespace>.servicebus.windows.net",
    eventhub_name="my-eventhub",
    consumer_group="$Default",
    credential=DefaultAzureCredential()
) as consumer:
    consumer.receive(
        on_event=on_event,
        starting_position="-1",  # Beginning of stream
    )
With Blob Checkpoint Store (Production)
from azure.eventhub import EventHubConsumerClient
from azure.eventhub.extensions.checkpointstoreblob import BlobCheckpointStore
from azure.identity import DefaultAzureCredential

checkpoint_store = BlobCheckpointStore(
    blob_account_url="https://<account>.blob.core.windows.net",
    container_name="checkpoints",
    credential=DefaultAzureCredential()
)

with EventHubConsumerClient(
    fully_qualified_namespace="<namespace>.servicebus.windows.net",
    eventhub_name="my-eventhub",
    consumer_group="$Default",
    credential=DefaultAzureCredential(),
    checkpoint_store=checkpoint_store
) as consumer:
    def on_event(partition_context, event):
        print(f"Received: {event.body_as_str()}")
        # Checkpoint after processing
        partition_context.update_checkpoint(event)

    consumer.receive(on_event=on_event)

Async Client

from azure.eventhub.aio import EventHubProducerClient, EventHubConsumerClient
from azure.identity.aio import DefaultAzureCredential
import asyncio

async def send_events():
    credential = DefaultAzureCredential()
    
    async with EventHubProducerClient(
        fully_qualified_namespace="<namespace>.servicebus.windows.net",
        eventhub_name="my-eventhub",
        credential=credential
    ) as producer:
        batch = await producer.create_batch()
        batch.add(EventData("Async event"))
        await producer.send_batch(batch)

async def receive_events():
    async def on_event(partition_context, event):
        print(event.body_as_str())
        await partition_context.update_checkpoint(event)
    
    async with EventHubConsumerClient(
        fully_qualified_namespace="<namespace>.servicebus.windows.net",
        eventhub_name="my-eventhub",
        consumer_group="$Default",
        credential=DefaultAzureCredential()
    ) as consumer:
        await consumer.receive(on_event=on_event)

asyncio.run(send_events())

Event Properties

event = EventData("My event body")

# Set properties
event.properties = {"custom_property": "value"}
event.content_type = "application/json"

# Read properties (on receive)
print(event.body_as_str())
print(event.sequence_number)
print(event.offset)
print(event.enqueued_time)
print(event.partition_key)

Get Event Hub Info

with producer:
    info = producer.get_eventhub_properties()
    print(f"Name: {info['name']}")
    print(f"Partitions: {info['partition_ids']}")
    
    for partition_id in info['partition_ids']:
        partition_info = producer.get_partition_properties(partition_id)
        print(f"Partition {partition_id}: {partition_info['last_enqueued_sequence_number']}")

Best Practices

  1. Pick sync OR async and stay consistent. Do not mix azure.xxx sync clients with azure.xxx.aio async clients in the same call path. Choose one mode per module.

  2. Always use context managers for clients and async credentials. Wrap every client in with Client(...) as client: (sync) or async with Client(...) as client: (async) for proper cleanup. For async DefaultAzureCredential from azure.identity.aio, also use async with credential: so tokens and transports are cleaned up.

  3. Use DefaultAzureCredential for portable auth across local dev and Azure (avoid connection strings / API keys when possible).

  4. Use batches for sending multiple events

  5. Use checkpoint store in production for reliable processing

  6. Use async client for high-throughput scenarios

  7. Use partition keys for ordered delivery within a partition

  8. Handle batch size limits — catch ValueError when batch is full

  9. Set appropriate consumer groups for different applications

Reference Files

FileContents
references/checkpointing.mdCheckpoint store patterns, blob checkpointing, checkpoint strategies
references/partitions.mdPartition management, load balancing, starting positions
scripts/setup_consumer.pyCLI for Event Hub info, consumer setup, and event sending/receiving

Files

scripts/setup_consumer.py

#!/usr/bin/env python3
"""
CLI tool for Azure Event Hubs consumer setup and monitoring.

Usage:
    # Show Event Hub info
    python setup_consumer.py info --namespace mynamespace --eventhub myeventhub
    
    # Show partition details
    python setup_consumer.py partitions --namespace mynamespace --eventhub myeventhub
    
    # Receive events (simple)
    python setup_consumer.py receive --namespace mynamespace --eventhub myeventhub
    
    # Receive with checkpointing
    python setup_consumer.py receive --namespace mynamespace --eventhub myeventhub \
        --storage-account mystorageaccount --checkpoint-container checkpoints
    
    # Receive from specific partition
    python setup_consumer.py receive --namespace mynamespace --eventhub myeventhub \
        --partition 0 --starting-position earliest
    
    # Send test events
    python setup_consumer.py send --namespace mynamespace --eventhub myeventhub \
        --message "Hello World" --count 10

Environment Variables:
    EVENT_HUB_FULLY_QUALIFIED_NAMESPACE: <namespace>.servicebus.windows.net
    EVENT_HUB_NAME: Event Hub name
    STORAGE_ACCOUNT_URL: https://<account>.blob.core.windows.net
    CHECKPOINT_CONTAINER: Checkpoint container name
"""

import argparse
import asyncio
import json
import os
import sys
from datetime import datetime, timezone
from typing import Optional

from azure.eventhub import EventData
from azure.eventhub.aio import EventHubConsumerClient, EventHubProducerClient
from azure.identity.aio import DefaultAzureCredential


async def get_eventhub_info(namespace: str, eventhub: str):
    """Display Event Hub information."""
    credential = DefaultAzureCredential()

    async with EventHubProducerClient(
        fully_qualified_namespace=namespace,
        eventhub_name=eventhub,
        credential=credential,
    ) as producer:
        props = await producer.get_eventhub_properties()

        print(f"Event Hub: {props['name']}")
        print(f"Created: {props['created_at']}")
        print(
            f"Partitions: {len(props['partition_ids'])} ({', '.join(props['partition_ids'])})"
        )


async def get_partition_info(namespace: str, eventhub: str):
    """Display detailed partition information."""
    credential = DefaultAzureCredential()

    async with EventHubProducerClient(
        fully_qualified_namespace=namespace,
        eventhub_name=eventhub,
        credential=credential,
    ) as producer:
        props = await producer.get_eventhub_properties()

        print(f"Event Hub: {props['name']}")
        print(f"Total Partitions: {len(props['partition_ids'])}")
        print("-" * 60)

        total_events = 0
        for partition_id in props["partition_ids"]:
            p_props = await producer.get_partition_properties(partition_id)

            begin_seq = p_props["beginning_sequence_number"]
            last_seq = p_props["last_enqueued_sequence_number"]
            event_count = last_seq - begin_seq if not p_props["is_empty"] else 0
            total_events += event_count

            print(f"\nPartition {partition_id}:")
            print(f"  Empty: {p_props['is_empty']}")
            print(f"  Sequence Range: {begin_seq} - {last_seq}")
            print(f"  Event Count (approx): {event_count}")
            print(f"  Last Offset: {p_props['last_enqueued_offset']}")
            print(f"  Last Enqueued: {p_props['last_enqueued_time_utc']}")

        print("-" * 60)
        print(f"Total Events (approx): {total_events}")


async def receive_events(
    namespace: str,
    eventhub: str,
    consumer_group: str = "$Default",
    partition_id: Optional[str] = None,
    starting_position: str = "latest",
    storage_account: Optional[str] = None,
    checkpoint_container: Optional[str] = None,
    max_events: int = 100,
    max_wait_time: float = 30.0,
):
    """Receive events from Event Hub."""
    credential = DefaultAzureCredential()
    checkpoint_store = None

    # Setup checkpoint store if provided
    if storage_account and checkpoint_container:
        from azure.eventhub.extensions.checkpointstoreblob.aio import (
            BlobCheckpointStore,
        )

        storage_url = f"https://{storage_account}.blob.core.windows.net"
        checkpoint_store = BlobCheckpointStore(
            blob_account_url=storage_url,
            container_name=checkpoint_container,
            credential=credential,
        )
        print(f"Using checkpoint store: {storage_url}/{checkpoint_container}")

    # Parse starting position
    if starting_position == "earliest":
        start_pos = "-1"
    elif starting_position == "latest":
        start_pos = "@latest"
    else:
        start_pos = starting_position

    event_count = 0

    async def on_event(partition_context, event):
        nonlocal event_count

        if event:
            event_count += 1
            print(
                f"\n[Partition {partition_context.partition_id}] Event {event_count}:"
            )
            print(f"  Sequence: {event.sequence_number}")
            print(f"  Offset: {event.offset}")
            print(f"  Enqueued: {event.enqueued_time}")

            body = event.body_as_str()
            if len(body) > 200:
                body = body[:200] + "..."
            print(f"  Body: {body}")

            if event.properties:
                print(f"  Properties: {event.properties}")

            # Checkpoint if store available
            if checkpoint_store:
                await partition_context.update_checkpoint(event)

        if event_count >= max_events:
            raise StopIteration("Max events reached")

    async def on_error(partition_context, error):
        if partition_context:
            print(f"Error in partition {partition_context.partition_id}: {error}")
        else:
            print(f"Error: {error}")

    consumer = EventHubConsumerClient(
        fully_qualified_namespace=namespace,
        eventhub_name=eventhub,
        consumer_group=consumer_group,
        credential=credential,
        checkpoint_store=checkpoint_store,
    )

    print(f"Receiving from Event Hub: {eventhub}")
    print(f"Consumer Group: {consumer_group}")
    print(f"Starting Position: {starting_position}")
    if partition_id:
        print(f"Partition: {partition_id}")
    print(f"Max Events: {max_events}")
    print("-" * 60)

    try:
        async with consumer:
            if partition_id:
                await consumer.receive(
                    on_event=on_event,
                    on_error=on_error,
                    partition_id=partition_id,
                    starting_position=start_pos,
                    max_wait_time=max_wait_time,
                )
            else:
                await consumer.receive(
                    on_event=on_event,
                    on_error=on_error,
                    starting_position=start_pos,
                    max_wait_time=max_wait_time,
                )
    except StopIteration:
        pass
    except KeyboardInterrupt:
        print("\nStopped by user")

    print(f"\n-" * 60)
    print(f"Total events received: {event_count}")


async def send_events(
    namespace: str,
    eventhub: str,
    message: str,
    count: int = 1,
    partition_key: Optional[str] = None,
    partition_id: Optional[str] = None,
):
    """Send test events to Event Hub."""
    credential = DefaultAzureCredential()

    async with EventHubProducerClient(
        fully_qualified_namespace=namespace,
        eventhub_name=eventhub,
        credential=credential,
    ) as producer:
        # Create batch with optional partition targeting
        batch_kwargs = {}
        if partition_id:
            batch_kwargs["partition_id"] = partition_id
            print(f"Sending to partition: {partition_id}")
        elif partition_key:
            batch_kwargs["partition_key"] = partition_key
            print(f"Using partition key: {partition_key}")

        batch = await producer.create_batch(**batch_kwargs)

        sent = 0
        for i in range(count):
            event_body = f"{message} #{i + 1}" if count > 1 else message
            event = EventData(event_body)
            event.properties = {
                "index": i,
                "timestamp": datetime.now(timezone.utc).isoformat(),
            }

            try:
                batch.add(event)
            except ValueError:
                # Batch full, send and create new
                await producer.send_batch(batch)
                sent += batch.size_in_bytes
                batch = await producer.create_batch(**batch_kwargs)
                batch.add(event)

        # Send remaining
        if batch:
            await producer.send_batch(batch)

        print(f"Sent {count} event(s) to {eventhub}")


def main():
    parser = argparse.ArgumentParser(
        description="Azure Event Hubs consumer setup and monitoring",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=__doc__,
    )

    subparsers = parser.add_subparsers(dest="command", help="Command to run")

    # Common arguments
    common = argparse.ArgumentParser(add_help=False)
    common.add_argument(
        "--namespace",
        "-n",
        default=os.environ.get("EVENT_HUB_FULLY_QUALIFIED_NAMESPACE"),
        help="Event Hub namespace (e.g., mynamespace.servicebus.windows.net)",
    )
    common.add_argument(
        "--eventhub",
        "-e",
        default=os.environ.get("EVENT_HUB_NAME"),
        help="Event Hub name",
    )

    # Info command
    info_parser = subparsers.add_parser(
        "info", parents=[common], help="Show Event Hub info"
    )

    # Partitions command
    partitions_parser = subparsers.add_parser(
        "partitions", parents=[common], help="Show partition details"
    )

    # Receive command
    receive_parser = subparsers.add_parser(
        "receive", parents=[common], help="Receive events"
    )
    receive_parser.add_argument(
        "--consumer-group",
        "-g",
        default="$Default",
        help="Consumer group (default: $Default)",
    )
    receive_parser.add_argument(
        "--partition", "-p", help="Specific partition to receive from"
    )
    receive_parser.add_argument(
        "--starting-position",
        choices=["earliest", "latest"],
        default="latest",
        help="Starting position (default: latest)",
    )
    receive_parser.add_argument(
        "--storage-account",
        default=os.environ.get("STORAGE_ACCOUNT_URL", "")
        .replace("https://", "")
        .replace(".blob.core.windows.net", ""),
        help="Storage account for checkpointing",
    )
    receive_parser.add_argument(
        "--checkpoint-container",
        default=os.environ.get("CHECKPOINT_CONTAINER"),
        help="Container for checkpoints",
    )
    receive_parser.add_argument(
        "--max-events",
        type=int,
        default=100,
        help="Maximum events to receive (default: 100)",
    )
    receive_parser.add_argument(
        "--max-wait-time",
        type=float,
        default=30.0,
        help="Max wait time in seconds (default: 30)",
    )

    # Send command
    send_parser = subparsers.add_parser(
        "send", parents=[common], help="Send test events"
    )
    send_parser.add_argument(
        "--message", "-m", default="Test event", help="Message to send"
    )
    send_parser.add_argument(
        "--count",
        "-c",
        type=int,
        default=1,
        help="Number of events to send (default: 1)",
    )
    send_parser.add_argument(
        "--partition-key", help="Partition key for consistent routing"
    )
    send_parser.add_argument("--partition-id", help="Specific partition ID to send to")

    args = parser.parse_args()

    # Validate common args
    if not args.command:
        parser.print_help()
        sys.exit(1)

    # Add .servicebus.windows.net if not present
    namespace = args.namespace
    if namespace and not namespace.endswith(".servicebus.windows.net"):
        namespace = f"{namespace}.servicebus.windows.net"

    if not namespace or not args.eventhub:
        print("Error: --namespace and --eventhub are required")
        sys.exit(1)

    # Run command
    try:
        if args.command == "info":
            asyncio.run(get_eventhub_info(namespace, args.eventhub))

        elif args.command == "partitions":
            asyncio.run(get_partition_info(namespace, args.eventhub))

        elif args.command == "receive":
            asyncio.run(
                receive_events(
                    namespace=namespace,
                    eventhub=args.eventhub,
                    consumer_group=args.consumer_group,
                    partition_id=args.partition,
                    starting_position=args.starting_position,
                    storage_account=args.storage_account
                    if args.storage_account
                    else None,
                    checkpoint_container=args.checkpoint_container,
                    max_events=args.max_events,
                    max_wait_time=args.max_wait_time,
                )
            )

        elif args.command == "send":
            asyncio.run(
                send_events(
                    namespace=namespace,
                    eventhub=args.eventhub,
                    message=args.message,
                    count=args.count,
                    partition_key=args.partition_key,
                    partition_id=args.partition_id,
                )
            )

    except Exception as e:
        print(f"Error: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an API key, Needs Python

Security

What our scanner noticed· Low risk

  • Instructions that use the network
  • Scripts that your agent may run

This skill includes scripts that your agent may run. Read them before you use it.

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Microsoft
Publisher
Microsoft (Official)
Source
microsoft/skills · .github/plugins/azure-sdk-python/skills/azure-eventhub-py · commit 0696600
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Microsoft or Microsoft.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download azure-eventhub-py.zip