multitasking: Non-blocking Python methods using decorators
MultiTasking is a lightweight Python library, currently at version 0.0.12, designed to convert Python methods into asynchronous, non-blocking methods using simple decorators. It is particularly effective for I/O-bound tasks such as API calls, web scraping, and database queries, enabling concurrent operations without complex manual thread or process management. The library focuses on ease of use and aims for a stable, albeit infrequent, release cadence with a focus on improvements rather than breaking changes.
Common errors
-
ModuleNotFoundError: No module named 'multitasking'
cause The 'multitasking' library has not been installed in the Python environment.fixInstall the library using pip: `pip install multitasking` -
AttributeError: 'module' object has no attribute 'task'
cause This error typically occurs if the 'task' decorator is misspelled or if a user attempts to call `multitasking.task()` as a function instead of using it as a decorator (`@multitasking.task`).fixEnsure the decorator is spelled correctly and used as `@multitasking.task` above the function definition. For example: ```python import multitasking import time @multitasking.task def my_task(): time.sleep(1) print('Task finished') my_task() multitasking.wait_for_tasks() ``` -
Tasks not running concurrently
cause This is a common behavioral issue where decorated tasks appear to run sequentially rather than in parallel, often due to `multitasking.wait_for_tasks()` being called prematurely within a loop or immediately after each task initiation, preventing true concurrency.fixEnsure that `multitasking.wait_for_tasks()` is called only after all desired tasks have been initiated, allowing them to run concurrently in the background. For example: ```python import multitasking import time @multitasking.task def my_task(task_id): print(f'Starting task {task_id}') time.sleep(2) print(f'Finished task {task_id}') for i in range(3): my_task(i) # Initiate tasks without waiting print('All tasks initiated, waiting for completion...') multitasking.wait_for_tasks() # Wait for all initiated tasks to finish print('All tasks completed') ```
Warnings
- gotcha Python's Global Interpreter Lock (GIL) limits true parallelism for CPU-bound tasks. While `multitasking` uses threads by default to achieve concurrency, CPU-intensive tasks will not run in parallel across multiple CPU cores due to the GIL, potentially leading to performance degradation from context switching rather than gains.
- gotcha By default, `multitasking` uses Python's `threading` module, which is efficient for I/O-bound operations (e.g., network requests, file I/O) where threads spend most of their time waiting for external resources. However, it's not optimal for CPU-bound tasks due to the GIL.
- gotcha The default maximum number of threads is typically based on the number of CPU cores. While `multitasking` automatically manages a pool, this default might not be optimal for all scenarios, especially when dealing with a very high number of short-lived I/O-bound tasks.
Install
-
pip install multitasking
Imports
- multitasking
import multitasking
- task
from multitasking import task
- wait_for_tasks
from multitasking import wait_for_tasks
Quickstart
import multitasking
import time
@multitasking.task
def fetch_data(url_id):
# Simulate API call or I/O operation
time.sleep(1)
print(f"Fetched data from URL {url_id}")
return f"Data from {url_id}"
if __name__ == "__main__":
print("Starting tasks...")
for i in range(5):
fetch_data(i)
# Wait for all tasks to complete
multitasking.wait_for_tasks()
print("All tasks completed!")