为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

DIEA 2022-09-13 19:58:56
我正在尝试为Python中长时间运行的任务生成轮询机制。为此,我使用并发未来并使用 进行轮询。该任务存在许多本身被阻塞的迭代,我将其包装在异步函数中。我无法访问阻止函数的代码,因为我正在调用第三方软件。这是我目前方法的一个最小例子:.done()import asyncioimport timeasync 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 pollingsleeping 0sleeping 1sleeping 2sleeping 3sleeping 4polling根据我目前对Python中asyncio机制的理解,我曾期望循环在第一次睡眠后解除阻塞,将控制权返回到poll_run语句的循环,并且只会在随后的轮询后运行long_running函数的第二次迭代。所以期望的输出是这样的:awaitbefore pollingsleeping 0pollingbefore pollingsleeping 1pollingbefore pollingsleeping 2pollingbefore pollingsleeping 3pollingbefore pollingsleeping 4polling这是否可以以某种方式通过当前方法实现,或者是否可能以不同的方式实现?编辑多亏了@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)
查看完整描述

1 回答

?
慕哥6287543

TA贡献1831条经验 获得超10个赞

time是同步库,并在执行时阻塞整个主线程。如果您的程序中有这样的阻塞调用,则可以避免使用线程或进程池执行器阻塞(您可以在此处阅读相关信息)。或者,将 “更改为”使用“而不是blocking_iterationasyncio.sleeptime.sleep


更新。为了清楚起见,这里是非阻塞版本,它与默认执行程序一起使用。请注意,现在没有loop.run_in_executorblocking_iterationasync


import asyncio

import concurrent.futures

import time


def 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()


查看完整回答
反对 回复 2022-09-13
  • 1 回答
  • 0 关注
  • 68 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信