you need to split the "worker" code into a separate function and use pool.apply_async to run your functions in parallel.

for writing to log files, make sure you do that in the main process to avoid race conditions, you can do it in the workers, but you'll need a lock for it to work properly.

the following demonstrates how to move all the worker logic to a separate function.

from multiprocessing import Pool

def worker_func(batch_num, batch):
    batch_results = []
    batch_logs = []

    print(f'----Batch {batch_num + 1} of {len(batches)}-------')
    batch_logs.append(f'\nBatch no {batch_num + 1} of {len(batches)} \n')

    # run loops and get results for the current batch
    for i, (k, v) in enumerate(batch):
        print(f'----Iteration {i + 1} of {len(batch)}-------')

        result, msg = run_model(k, v, param)
        batch_results.append(result)
        batch_logs.append(msg)

    # Combine the results and save the output files
    batch_results = pd.concat(batch_results)
    batch_results = batch_results.reset_index(drop=True)
    return batch_logs

if __name__ == '__main__':
    # Create a list of tuples with each key and the corresponding df for each key
    site_data = [(site, df) for site, df in df.groupby('site')]

    # set batch size
    batch_size = 1000

    # split dictionary into batches
    batches = [
        site_data[i:i + batch_size] for i in range(0, len(site_data), batch_size)
    ]

    with Pool() as pool:
        futures = []
        # loop through each batch
        for batch_num, batch in enumerate(batches):
            futures.append(pool.apply_async(worker_func, batch_num, batch))

        for future in futures:
            batch_logs = future.get()  # wait for work to be done
            # Save logs to the file
            log_file = f"logs/logs_{today}"
            # write to log from main process to avoid race conditions
            save_logs(log_file, batch_logs)
Answer from Ahmed AEK on Stack Overflow
🌐
Medium
medium.com › data-science › parallel-batch-processing-in-python-8dcce607d226
Parallel batch processing in Python | by Dennis Bakhuis | TDS Archive | Medium
December 28, 2021 - Parallel batch processing in Python Process in batches using joblib and show progress with tqdm Joblib is a great tool for parallelization but sometimes it is better to process the workload in …
🌐
Stack Overflow
stackoverflow.com › questions › 54160617 › python-parallel-batch-processing-of-files-in-a-directory
Python - Parallel + Batch processing of files in a directory - Stack Overflow
Depending on how many workers you have, I suggest to increase the batch size to be more than 100, to reduce the time in which you have idle workers (as detailed above). Assuming you just want groups of 100 consecutive files, but not necessarily from the beginning, you can try the following. By the math suggested, I'd say that you can divide the files into groups of 100, and then process each group in a separate worker (So the parallelization is on groups, but once each group is done, you know 100 consecutive files are processed).
🌐
Microsoft Learn
learn.microsoft.com › en-us › azure › batch › tutorial-parallel-python
Tutorial: Run a parallel workload using the Python API - Azure Batch | Microsoft Learn
August 4, 2026 - Learn how to process media files in parallel using ffmpeg in Azure Batch with the Batch Python client library.
🌐
Hevo
hevodata.com › home › learn › data strategy
Python Batch Processing: The Best Guide | Hevo
January 9, 2026 - The code imports Parallel and delayed from joblib for parallel processing. It also imports tqdm for a progress bar. The function batch_process_function(order, payload=None) approximates π using the Leibniz series.
🌐
OneUptime
oneuptime.com › home › blog › how to process datasets with parallel jobs in python
How to Process Datasets with Parallel Jobs in Python
January 23, 2026 - Modern machines have multiple CPU cores, but in the standard GIL-enabled CPython build, the Global Interpreter Lock (GIL) prevents multiple threads from executing Python bytecode at the same time. For CPU-bound tasks like data transformation, multiprocessing is usually the better fit. For I/O-bound tasks, threading or async can work. This guide covers both scenarios with practical code you can adapt. Different workloads need different parallelization strategies: flowchart TD A[Data Processing Task] --> B{CPU-bound or I/O-bound?} B -->|CPU-bound| C{Dataset Size?} B -->|I/O-bound| D[Use threading or asyncio] C -->|Small to Medium| E[multiprocessing.Pool] C -->|Large| F[Consider chunking + Pool] C -->|Very Large| G[Dask or Spark]
Top answer
1 of 1
1

you need to split the "worker" code into a separate function and use pool.apply_async to run your functions in parallel.

for writing to log files, make sure you do that in the main process to avoid race conditions, you can do it in the workers, but you'll need a lock for it to work properly.

the following demonstrates how to move all the worker logic to a separate function.

from multiprocessing import Pool

def worker_func(batch_num, batch):
    batch_results = []
    batch_logs = []

    print(f'----Batch {batch_num + 1} of {len(batches)}-------')
    batch_logs.append(f'\nBatch no {batch_num + 1} of {len(batches)} \n')

    # run loops and get results for the current batch
    for i, (k, v) in enumerate(batch):
        print(f'----Iteration {i + 1} of {len(batch)}-------')

        result, msg = run_model(k, v, param)
        batch_results.append(result)
        batch_logs.append(msg)

    # Combine the results and save the output files
    batch_results = pd.concat(batch_results)
    batch_results = batch_results.reset_index(drop=True)
    return batch_logs

if __name__ == '__main__':
    # Create a list of tuples with each key and the corresponding df for each key
    site_data = [(site, df) for site, df in df.groupby('site')]

    # set batch size
    batch_size = 1000

    # split dictionary into batches
    batches = [
        site_data[i:i + batch_size] for i in range(0, len(site_data), batch_size)
    ]

    with Pool() as pool:
        futures = []
        # loop through each batch
        for batch_num, batch in enumerate(batches):
            futures.append(pool.apply_async(worker_func, batch_num, batch))

        for future in futures:
            batch_logs = future.get()  # wait for work to be done
            # Save logs to the file
            log_file = f"logs/logs_{today}"
            # write to log from main process to avoid race conditions
            save_logs(log_file, batch_logs)
🌐
KDnuggets
kdnuggets.com › 2022 › 07 › parallel-processing-large-file-python.html
Parallel Processing Large File in Python - KDnuggets
We will get English stopwords using nltk.copus the use it to filter out stop words from the text line. After that, we will remove special characters and extra spaces from the sentence. It will be the baseline function to determine processing time for serial, parallel, and batch processing.
Find elsewhere
🌐
Projectpy
projectpy.com › home › python-basics › implementing efficient batch processing in python: a comprehensive guide
Implementing Efficient Batch Processing in Python: A Comprehensive Guide - Learn the smart way...
January 7, 2026 - Next, we implement parallel batch processing using ThreadPoolExecutor. This allows multiple prompts to be processed simultaneously. As shown in the implementation, this method takes advantage of Python’s threading capabilities to improve ...
🌐
Read Medium
readmedium.com › parallel-batch-processing-in-python-8dcce607d226
Parallel batch processing in Python
The article provides an in-depth exploration of parallel batch processing in Python, emphasizing the importance of leveraging multi-core CPUs for data processing tasks. It introduces joblib as a tool for parallelization and demonstrates its ease of use compared to Python's built-in multiprocessing and threading modules.
🌐
Kitchin Research Group
kitchingroup.cheme.cmu.edu › pycse › book › 24-parallel-processing.html
Parallel Processing in Python — pycse - Python Computations in Science and Engineering
Examples include: Parameter sweeps: solving an ODE with 1000 different rate constants · Monte Carlo simulations: running 10,000 random trials for uncertainty quantification · Batch processing: analyzing hundreds of experimental data files · Cross-validation: training models on different ...
🌐
Wpcomstaging
waterprogramming.wpcomstaging.com › 2021 › 11 › 10 › easy-batch-parallelization-of-code-in-any-language-using-mpi4py
Easy batch parallelization of code in any language using mpi4py – Water Programming: A Collaborative Research Blog
November 10, 2021 - The processors running each task can access their own rank number, which will play an important role in how we use MPI for embarrassingly parallel applications. A example schematic of the MPI_COMM_WORLD communicator with six tasks and their associated ranks is shown below. MPI is implemented in Python with the mpi4py library.
🌐
PyPI
pypi.org › project › batch-processing
batch-processing · PyPI
September 2, 2023 - In case of grouped inputs, the first argument of the batch processing function becomes a list of Path instead of a single Path: def parallel_process(inputs: list[Path], output: Path, args): # Load the input files, apply some processing, and save to output file here
🌐
Talent500
talent500.com › home › blog › mastering batch processing in python: data handling techniques
Mastering Batch Processing in Python: Data Handling Techniques
December 1, 2025 - We assume that you have Python and Pandas installed on your system. ... import pandas as pd # Function to process each batch def process_batch(batch_data): # Perform data transformations here processed_data = batch_data.apply(lambda x: x * 2) # Example transformation: doubling the values return processed_data # Read the CSV file in chunks chunk_size = 100000 # Adjust the chunk size as per your system's memory constraints csv_file = "large_data.csv" # Replace with your CSV file's path output_file = "processed_data.csv" # Replace with the desired output file path # Read the CSV file in batches and process each batch for chunk in pd.read_csv(csv_file, chunksize=chunk_size): processed_chunk = process_batch(chunk) processed_chunk.to_csv(output_file, mode="a", header=False, index=False)
🌐
Medium
medium.com › @RampantLions › efficient-parallel-batch-computation-in-python-streaming-results-with-multiprocessing-and-smart-8f6a1507e891
Efficient Parallel Batch Computation in Python: Streaming Results with Multiprocessing and Smart Sizing | by Josh Wiechman | Medium
June 20, 2025 - When working with computationally heavy tasks or large data batches, leveraging all available CPU cores can make a massive difference in runtime. But parallelism is more than just spinning up a few threads or processes, you need to stream results as they’re ready and avoid overloading your system. Here’s a pattern that uses Python’s multiprocessing.Pool, result streaming, and system-aware sizing for maximum efficiency.
🌐
LinkedIn
linkedin.com › pulse › data-parallel-processing-python-warren-jitsing
Data Parallel Processing with Python
August 24, 2021 - The batch method allows multiple items of work to be submitted to the pool of processes, while the single method allows work to be submitted one item at a time. The shutdown method just cleans up the ProcessPoolExecutor. class ProcessPool: """ ...
🌐
OneUptime
oneuptime.com › home › blog › how to handle batch processing optimization
How to Handle Batch Processing Optimization
January 24, 2026 - from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor import multiprocessing def process_chunk(chunk): """Process a single chunk - must be picklable for ProcessPoolExecutor""" results = [] for record in chunk: # CPU-intensive processing result = transform_record(record) results.append(result) return results def parallel_batch_process(data_source, chunk_size=1000, max_workers=None): """Process data in parallel using multiple processes""" if max_workers is None: max_workers = multiprocessing.cpu_count() all_results = [] # Use ProcessPoolExecutor for CPU-bound work # Use ThreadPo
🌐
Mpasdiag
mpasdiag.com › home › documentation › user guide › parallel & batch processing
Parallel & Batch Processing | MPASdiag.com
June 16, 2026 - --workers defaults to the detected CPU-core count; the equivalent MPASConfig fields are parallel: true and workers. ... You must launch under the MPI runtime. Running a script directly will not use MPI even if mpi4py is installed: mpiexec -n 8 mpasdiag precipitation --grid-file grid.nc --data-dir ./data \ --variable total --batch-all mpiexec -n 8 python my_batch_script.py
🌐
NERSC
docs.nersc.gov › development › languages › python › parallel-python
Parallel Python - NERSC Documentation
Since you are running at NERSC you may be interested in parallelizing your Python code and/or its I/O. This is a detailed topic but we will provide a short overview of several options. If you intend to to run your code at scale, please see our discussion on scaling Python that provides a brief overview of best file system practices for scaling up. Python's standard library provides a multiprocessing package that supports spawning of processes.
🌐
DEV Community
dev.to › jamesli › llm-parallel-processing-in-practice-key-techniques-for-performance-enhancement-20g0
LLM Parallel Processing in Practice: Key Techniques for Performance Enhancement - DEV Community
November 18, 2024 - from typing import List, Dict, Any from dataclasses import dataclass import asyncio from langchain.chat_models import ChatOpenAI from langchain.callbacks import AsyncCallbackHandler @dataclass class BatchConfig: """Batch processing configuration""" batch_size: int = 5 max_concurrent_tasks: int = 3 timeout_seconds: int = 30 retry_attempts: int = 2 class BatchProcessor: def __init__(self, config: BatchConfig): self.config = config self.llm = ChatOpenAI( temperature=0, request_timeout=config.timeout_seconds ) self.semaphore = asyncio.Semaphore( config.max_concurrent_tasks ) async def process_batch( self, items: List[Any] ) -> List[Dict]: """Main batch processing function""" batches = self._create_batches(items) results = [] for batch in batches: batch_results = await self._process_batch_with_semaphore( batch ) results.extend(batch_results) return results
🌐
Cornell University
people.orie.cornell.edu › vc333 › orie5270 › lectures › 09
Weeks 9 - 10: Parallel processing in Python - ORIE 5270 / 6125
However, for CPU-bound tasks, the multiprocessing library presented below is the recommended approach to achieve parallelism. Multiprocessing in Python is possible via the homonymous library, which allows a "master" or base process to spawn several other Python processes, each of them effectively running in a separate Python environment.