Registry / workflow / aiomultiprocess

aiomultiprocess

JSON →
library0.9.1pypypi✓ verified 24d ago

aiomultiprocess is a Python library that provides an asynchronous version of the standard `multiprocessing` module, combining the benefits of `asyncio` for I/O-bound tasks and `multiprocessing` for CPU-bound tasks. It runs a full `asyncio` event loop on each child process, enabling high levels of concurrency and parallelism beyond the Global Interpreter Lock (GIL). The library is actively maintained, with its current version being 0.9.1.

pip install aiomultiprocess
INSTALL
IMPORT
SIG · AIOMULTIPROCESS
A
aiomultiprocess
workflowpythonv0.9.1
Install
1.5s avg
Import
349ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.9.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.382s · 17.9MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.5s · import 0.316s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Pool
from aiomultiprocess import Pool
The primary class for managing a pool of worker processes.
Process
from aiomultiprocess import Process
For running a single coroutine in a dedicated subprocess, similar to `multiprocessing.Process`.
Worker
from aiomultiprocess import Worker
Similar to `Process` but specifically designed to return results from a coroutine task in a subprocess.

This quickstart demonstrates using `aiomultiprocess.Pool` to fetch multiple URLs concurrently across several processes. It defines an asynchronous function `fetch_url_content` that uses `aiohttp` to make an HTTP GET request. The `main` function then creates a `Pool` and uses its `map` method to distribute the `fetch_url_content` coroutine calls across the worker processes, iterating over results as they complete.

import asyncio from aiohttp import ClientSession from aiomultiprocess import Pool async def fetch_url_content(url: str) -> str: """An example async coroutine to be run by the pool.""" async with ClientSession() as session: async with session.get(url) as response: response.raise_for_status() # Raise an exception for bad status codes return await response.text() async def main(): urls = [ "https://www.google.com", "https://www.python.org", "https://docs.python.org/3/library/asyncio.html", "https://www.wikipedia.org" ] print(f"Fetching {len(urls)} URLs using aiomultiprocess Pool...") async with Pool(processes=2) as pool: # Use 2 processes for demonstration # Use pool.map to apply the coroutine to each URL async for result in pool.map(fetch_url_content, urls): if result: # Check if result is not None (e.g., if an exception was caught by handler) print(f"Fetched content size: {len(result)} bytes for one URL.") else: print("Failed to fetch content for a URL.") if __name__ == '__main__': # Ensure aiohttp is installed for this example: pip install aiohttp try: asyncio.run(main()) except ImportError: print("Please install aiohttp for this example: pip install aiohttp") except Exception as e: print(f"An error occurred: {e}")
Debug
Known issues
breakingBy default, aiomultiprocess uses 'spawned' processes on all platforms, which is different from the standard `multiprocessing` module's default 'forked' on Linux/macOS (for Python versions prior to 3.8). This means any objects or coroutines passed to child processes *must* be pickleable (importable from a fresh child process). Unpickleable objects will cause errors.
fix
Ensure all functions, classes, and global objects passed to worker processes are defined at the top-level of a module and are importable. If 'forked' behavior is strictly required (e.g., for sharing non-pickleable resources that are copied by fork), call `aiomultiprocess.set_start_method('fork')` before creating any workers or pools.
affects: <=0.9.1
gotchaGlobal variables and shared state behave differently with spawned processes. Each child process gets its own independent memory space; changes to global variables in one process are not reflected in others. This can lead to unexpected behavior if not accounted for.
fix
Avoid relying on shared mutable global state. Use queues (`multiprocessing.Manager().Queue()`) for explicit inter-process communication or pass data explicitly as arguments and return values. For resource initialization per process, use the `initializer` and `initargs` parameters of the `Pool` constructor.
affects: <=0.9.1
gotchaExceptions raised within worker processes are automatically caught and re-raised in the main process as `ProxyException` objects. While convenient, this might obscure the original traceback or prevent in-worker exception handling (e.g., for logging or reporting).
fix
To handle exceptions within the worker process itself, provide an `exception_handler` callable to the `Pool` (or `Process`/`Worker`) constructor. This handler will be called with the exception object before it's propagated back to the main process.
affects: <=0.9.1
gotchaLong-running tasks or high concurrency with `aiomultiprocess.Pool` can sometimes lead to 'OSError: [Errno 24] Too many open files' or memory leaks if worker processes are not periodically refreshed.
fix
Utilize the `maxtasksperchild` parameter when creating a `Pool`. Setting it to a positive integer will cause worker processes to exit and be respawned after completing the specified number of tasks, helping to release resources and prevent file handle exhaustion.
affects: <=0.9.1
gotchaIf you are using an alternative `asyncio` event loop implementation (e.g., `uvloop`), `aiomultiprocess` will not automatically use it in child processes. The default `asyncio` loop will be used instead, potentially leading to suboptimal performance.
fix
Explicitly specify the event loop initializer using the `loop_initializer` parameter in the `Pool` (or `Process`/`Worker`) constructor. For `uvloop`, this would be `loop_initializer=uvloop.new_event_loop`.
affects: <=0.9.1
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'aiomultiprocess'
The 'aiomultiprocess' package is not installed in the Python environment.
fix
Install the package using pip: 'pip install aiomultiprocess'.
RuntimeWarning: coroutine 'main' was never awaited
The asynchronous function 'main()' was defined but not awaited, leading to a coroutine that was never executed.
fix
Ensure that the 'main()' coroutine is properly awaited by using 'asyncio.run(main())' in Python 3.7+, or 'loop = asyncio.get_event_loop(); loop.run_until_complete(main())' in Python 3.6.
ModuleNotFoundError: No module named 'aiohttp'
The 'aiohttp' package, which is a dependency for 'aiomultiprocess', is not installed in the Python environment.
fix
Install the 'aiohttp' package using pip: 'pip install aiohttp'.
_pickle.PicklingError: Can't pickle <function ...>: attribute lookup ... failed
Objects (especially functions or class methods) passed to `aiomultiprocess.Pool` or `Process` must be picklable. This error often occurs when trying to pickle local, nested, or dynamically created functions/objects, or certain complex objects that cannot be serialized across process boundaries.
fix
Ensure that functions and objects intended for use in child processes are defined at the top-level of a module, making them importable by the new process. Avoid using `lambda` functions or nested function definitions as targets for multiprocessing tasks. If passing complex objects, ensure they are serializable or use an initializer function for setup within the child processes.
RuntimeError: Cannot run the event loop while another loop is running
This error occurs when attempting to start a new `asyncio` event loop (e.g., with `asyncio.run()`) in a thread or process where an event loop is already active. This is a common `asyncio` pitfall that can occur when `aiomultiprocess` is misused, for example, if a child process inadvertently tries to create a new loop without proper handling.
fix
Ensure that `asyncio.run()` or `loop.run_until_complete()` is called only once per thread/process to manage the top-level event loop. In child processes managed by `aiomultiprocess`, the event loop is usually set up automatically; avoid explicitly calling `asyncio.run()` within the target functions executed by the pool or worker, unless you are deliberately managing separate loops in a highly specific way.
Upgrade
Version history
0.9.1latest on PyPI · released Apr 23, 2024
Audit
Dependencies
pythonrequiredRequires Python 3.8 or newer for full functionality and compatibility.
aiohttpoptionalCommonly used in examples for asynchronous network requests within worker processes.
Agent activity
55 hits · last 30 days
node
46
OpenAI (training)
1
Resources
aiomultiprocess — pip install aiomultiprocess · libregistry