thread retardo poner microseconds funcion delays python python-3.x asynchronous python-asyncio aiohttp

python - retardo - ¿Cómo puedo envolver una función síncrona en una rutina de Async?



set a delay in python (3)

Estoy usando aiohttp para construir un servidor de API que envíe solicitudes de TCP a un servidor separado. El módulo que envía las solicitudes TCP es síncrono y una caja negra para mis propósitos. Así que mi problema es que estas solicitudes están bloqueando la API completa. Necesito una forma de envolver las solicitudes de módulo en una rutina asíncrona que no bloquee el resto de la API.

Entonces, solo usando el modo de sleep como un ejemplo simple, ¿hay alguna manera de envolver de alguna manera el código síncrono que consume mucho tiempo en una computadora sin bloqueo, algo como esto:

async def sleep_async(delay): # After calling sleep, loop should be released until sleep is done yield sleep(delay) return ''I slept asynchronously''


Finalmente encontré una respuesta en este hilo . El método que estaba buscando es run_in_executor . Esto permite que una función síncrona se ejecute de forma asíncrona sin bloquear un bucle de eventos.

En el ejemplo de sleep que publiqué arriba, podría verse así:

import asyncio from time import sleep from concurrent.futures import ProcessPoolExecutor async def sleep_async(loop, delay): # Can set executor to None if a default has been set for loop await loop.run_in_executor(ProcessPoolExecutor(), sleep, delay) return ''I slept asynchronously''

También vea la siguiente respuesta -> ¿Cómo llamamos una función normal donde se espera una coroutine?


No estoy seguro si es demasiado tarde, pero también puedes usar un decorador para hacer tu función en un hilo. AUNQUE, tenga en cuenta que seguirá siendo un bloqueo no coop a diferencia de async que es el bloqueo cooperativo.

def wrap(func): from concurrent.futures import ThreadPoolExecutor pool=ThreadPoolExecutor() @wraps(func) async def run(*args, loop=None, executor=None, **kwargs): if loop is None: loop = asyncio.get_event_loop() future=pool.submit(func, *args, **kwargs) return asyncio.wrap_future(future) return run

¡Espero que ayude!


Puede utilizar un decorador para ajustar la versión de sincronización a una versión asíncrona.

import time from functools import wraps, partial def wrap(func): @wraps(func) async def run(*args, loop=None, executor=None, **kwargs): if loop is None: loop = asyncio.get_event_loop() pfunc = partial(func, *args, **kwargs) return await loop.run_in_executor(executor, pfunc) return run @wrap def sleep_async(delay): time.sleep(delay) return ''I slept asynchronously''

o usa el aioify lib

% pip install aioify

entonces

@aioify def sleep_async(delay): pass