import asyncio import functools from concurrent.futures import ThreadPoolExecutor _pool = ThreadPoolExecutor(max_workers=32, thread_name_prefix="dfu") async def run_blocking(func, /, *args, **kwargs): loop = asyncio.get_running_loop() return await loop.run_in_executor(_pool, functools.partial(func, *args, **kwargs)) def threaded(func): @functools.wraps(func) async def wrapper(*args, **kwargs): return await run_blocking(func, *args, **kwargs) return wrapper def spawn(coro, *, name=None): task = asyncio.create_task(coro, name=name) def _done(t): if not t.cancelled() and t.exception(): print(f"task {name or ''} error: {t.exception()!r}") task.add_done_callback(_done) return task def shutdown(): _pool.shutdown(wait=False, cancel_futures=True)