Python async await 不等待

Python async await not waiting

我对异步的工作不多python,但目前我有一个使用 Sanic 框架的项目。有一个 websocket 端点,它从客户端接收数据,向客户端发送消息,该任务已经启动,然后运行长同步任务(没有使其异步的选项),最后向客户端发送消息,任务完成。有一些示例代码:

from sanic import Sanic
from sanic.server.protocols.websocket_protocol import WebSocketProtocol

app = Sanic("TestApp")

@app.websocket("/")
async def process_task(request, ws: WebSocketServerProtocol):
    raw_data = await ws.recv()
    data = json.loads(raw_data)
    await ws.send("TASK STARTED")
    process_long_task(data) # Long sync function
    await ws.send("TASK ENDED")

但是有个问题。函数不等待 ws.send("TASK STARTED")。实际上这两条消息都是在 process_long_task 完成后才发送的。虽然,如果我在 await ws.send("TASK STARTED")

之后添加 await asyncio.sleep(0.1) 它会正常工作

有人可以指出我的代码有什么问题吗?

如果您从协程调用同步函数,整个循环和其中的所有任务 运行 将等待该同步函数完成。

如果您需要一个长 运行 同步函数,并异步等待结果,有几种方法,大多数人使用某种后台线程。

这是一个异步使用 socket.gethostbyaddr()(有时完成同步功能非常慢)的示例。

async def GetHostFromAddr(ip):
    """
    GetHostFromAddr(ip) -> fqdn\n
    :param ip: The hosts ip address ie. 192.168.1.1
    :return: Return the fqdn (a string of the form 'sub.example.com') for a host.
    """
    loop = asyncio.get_event_loop()
    event = asyncio.Event()
    pool = ThreadPool(processes=1)

    thread_result = pool.apply_async(gethostbyaddr, (ip,), callback=lambda x: loop.call_soon_threadsafe(event.set))

    with contextlib.suppress(asyncio.TimeoutError):
        if await asyncio.wait_for(event.wait(), 5):
            event.clear()
            return thread_result.get()[0]
        else:
            event.clear()
            pool.terminate()