How to Mock Spark Streaming Micro-Batches in Python

Simulate Spark's micro-batch streaming with a simple deque-based class that collects events over time and processes them in timed batches.

Medium Python 3.9+ Aug 9, 2026 Big data & Spark 13 views 0 copies

Python code

47 lines
Python 3.9+
import time
from collections import deque
from datetime import datetime


class MicroBatchStream:
    def __init__(self, batch_interval_sec=2):
        self.batch_interval = batch_interval_sec
        self.source = deque()
        self.processed = []

    def add_events(self, events):
        self.source.extend(events)

    def process_batch(self):
        batch = []
        batch_end = time.time() + self.batch_interval
        while time.time() < batch_end and self.source:
            batch.append(self.source.popleft())

        if batch:
            self.processed.extend(batch)
            print(f"[{datetime.now().strftime('%H:%M:%S')}] "
                  f"processed {len(batch)} events: {batch}")
        else:
            print(f"[{datetime.now().strftime('%H:%M:%S')}] empty batch")

        return batch


if __name__ == "__main__":
    stream = MicroBatchStream(batch_interval_sec=1)

    # Simulate incoming events over time
    stream.add_events(["click", "view", "purchase"])
    time.sleep(0.3)
    stream.add_events(["login", "logout"])
    time.sleep(0.5)
    stream.add_events(["search", "filter"])

    # Run 3 micro-batches
    for _ in range(3):
        batch = stream.process_batch()
        time.sleep(0.5)

    print(f"\nTotal processed: {len(stream.processed)}")
    print(f"Remaining in source: {len(stream.source)}")

Output

stdout
[14:23:45] processed 3 events: ['click', 'view', 'purchase']
[14:23:46] processed 2 events: ['login', 'logout']
[14:23:47] processed 2 events: ['search', 'filter']

Total processed: 7
Remaining in source: 0

How it works

The MicroBatchStream class mimics Spark Streaming's micro-batch model by accumulating events in a deque and draining them every batch_interval seconds. process_batch() blocks until the interval elapses or the source is empty, then moves available events to the processed list and prints a log line. This simulation is useful for testing stream-processing logic without a Spark cluster. The time-based loop uses time.time() to ensure batches are sized by wall-clock time, not CPU iterations.

Common mistakes

  • Assuming `deque.popleft()` is thread-safe; it is not, so use a lock in multi-threaded scenarios.
  • Using `time.sleep()` inside the batch loop increases latency; prefer a non-blocking check or a timer.
  • Not handling the case where `source` is empty but the batch window hasn't elapsed, leading to wasted wait time.
  • Forgetting that `deque` is not sorted; events are processed in insertion order, which may not match event timestamps.

Variations

  1. Use `asyncio` with `asyncio.sleep` for an asynchronous micro-batch stream.
  2. Replace `deque` with `queue.Queue` to support multiple producer threads.

Real-world use cases

  • Unit-testing Spark Structured Streaming transformations locally without spinning up a Spark session.
  • Load-testing downstream sinks with predetermined event bursts before deploying to production.
  • Debugging checkpoint and stateful aggregation logic by replaying event logs through a mock stream.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Big data & Spark

Related tutorials and quizzes for this topic.