Executors¶
Executors are responsible for actually running task callables after the scheduler decides they are due.
Built-in executors¶
AsyncIOExecutor¶
Runs work on the scheduler event loop. Coroutine functions are awaited directly. Regular callables run through the loop's default executor.
- Plugin alias:
asyncio
ThreadPoolExecutor¶
Runs work in a concurrent.futures.ThreadPoolExecutor.
- Plugin aliases:
pool,threadpool - Best for: blocking I/O or code that should not block the event loop
Parameters:
max_workerspool_kwargscancel_futuresoverwrite_wait
ProcessPoolExecutor¶
Runs work in a concurrent.futures.ProcessPoolExecutor.
- Plugin alias:
processpool - Best for: CPU-bound work that benefits from process isolation
Parameters:
max_workerspool_kwargscancel_futuresoverwrite_wait
DebugExecutor¶
Executes the task inline instead of deferring it to another thread or process. This is useful in tests or while debugging task behavior.
- Plugin alias:
debug
Choosing an executor¶
- Use
asynciofor coroutine-heavy workloads. - Use
threadpoolfor blocking I/O that should not block the loop. - Use
processpoolfor CPU-bound functions that are safe to pickle. - Use
debugfor deterministic local testing.
Logger namespaces¶
Executors log through:
Custom executors¶
Custom executors must subclass BaseExecutor and implement at least:
start()shutdown()do_send_task()
from datetime import datetime
from typing import Any, List
from asyncz.executors.base import BaseExecutor
from asyncz.schedulers import AsyncIOScheduler
from asyncz.tasks.types import TaskType
class CustomExecutor(BaseExecutor):
"""
A new custom executor.
"""
def start(self, scheduler: Any, alias: str): ...
def shutdown(self, wait: bool = True): ...
def send_task(self, task: "TaskType", run_times: List[datetime]): ...
def do_send_task(self, task: "TaskType", run_times: List[datetime]) -> Any: ...
# Create executor
executor = CustomExecutor()
scheduler = AsyncIOScheduler()
# Add custom executor
scheduler.add_executor(executor, "cutom")