并发轮询一系列阻塞呼叫的未来

我正在尝试为Python中长时间运行的任务生成轮询机制。为此,我使用并发未来并使用 进行轮询。该任务存在许多本身被阻塞的迭代,我将其包装在异步函数中。我无法访问阻止函数的代码,因为我正在调用第三方软件。这是我目前方法的一个最小例子:.done()


import asyncio

import time


async def blocking_iteration():

    time.sleep(1)


async def long_running():

    for i in range(5):

        print(f"sleeping {i}")

        await blocking_iteration()


async def poll_run():

    future = asyncio.ensure_future(long_running())

    while not future.done():

        print("before polling")

        await asyncio.sleep(0.05)

        print("polling")

    future.result()


if __name__ == '__main__':

    loop = asyncio.get_event_loop()

    loop.run_until_complete(poll_run())

    loop.close()

这样做的结果是:


before polling

sleeping 0

sleeping 1

sleeping 2

sleeping 3

sleeping 4

polling

根据我目前对Python中asyncio机制的理解,我曾期望循环在第一次睡眠后解除阻塞,将控制权返回到poll_run语句的循环,并且只会在随后的轮询后运行long_running函数的第二次迭代。所以期望的输出是这样的:await


before polling

sleeping 0

polling

before polling

sleeping 1

polling

before polling

sleeping 2

polling

before polling

sleeping 3

polling

before polling

sleeping 4

polling

这是否可以以某种方式通过当前方法实现,或者是否可能以不同的方式实现?


编辑


多亏了@drjackild才能够通过改变来解决这个问题。


async def blocking_iteration():

    time.sleep(1)


def blocking():

    time.sleep(1)


async def blocking_iteration():

    loop = asyncio.get_event_loop()

    await loop.run_in_executor(None, blocking)


DIEA
浏览 69回答 1
1回答

慕哥6287543

time是同步库,并在执行时阻塞整个主线程。如果您的程序中有这样的阻塞调用,则可以避免使用线程或进程池执行器阻塞(您可以在此处阅读相关信息)。或者,将 “更改为”使用“而不是blocking_iterationasyncio.sleeptime.sleep更新。为了清楚起见,这里是非阻塞版本,它与默认执行程序一起使用。请注意,现在没有loop.run_in_executorblocking_iterationasyncimport asyncioimport concurrent.futuresimport timedef blocking_iteration():    time.sleep(1)async def long_running():    loop = asyncio.get_event_loop()    for i in range(5):        print(f"sleeping {i}")        await loop.run_in_executor(None, blocking_iteration)async def poll_run():    task = asyncio.create_task(long_running())    while not task.done():        print("before polling")        await asyncio.sleep(0.05)        print("polling")    print(task.result())if __name__ == '__main__':    loop = asyncio.get_event_loop()    loop.run_until_complete(poll_run())    loop.close()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python