首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从同步代码中调度任务以运行事件循环

从同步代码中调度任务以运行事件循环
EN

Stack Overflow用户
提问于 2018-01-28 02:52:28
回答 1查看 806关注 0票数 1

考虑这个程序,其中用于停止它的主循环和协程实际上是由我正在使用的一个库实现的。

代码语言:javascript
复制
import asyncio
import signal

running = True

async def stop():
    global running
    print("setting false")
    running = False
    await asyncio.sleep(3)
    print("reached end")

async def mainloop():
    while running:
        print("loop")
        await asyncio.sleep(1)

def handle_signal():
    loop.create_task(stop())

loop = asyncio.get_event_loop()
loop.add_signal_handler(signal.SIGINT, handle_signal)
loop.run_until_complete(mainloop())
loop.close()

当程序收到信号时,我需要调用stop协程来停止主循环。虽然在使用asyncio.BaseEventLoop.create_task调度停止协程时,它首先会停止主循环,这会停止事件循环,但停止协程无法完成:

代码语言:javascript
复制
$ ./test.py 
loop
loop
loop
^Csetting false
Task was destroyed but it is pending!
task: <Task pending coro=<stop() done, defined at ./test.py:7> wait_for=<Future pending cb=[Task._wakeup()]>>

如何将协程添加到正在运行的事件循环中,同时使事件循环等待完成?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-28 03:23:59

正如您所发现的,问题在于事件循环只等待mainloop()完成,留下stop()挂起,asyncio正确地抱怨了这一点。

如果handle_signal和顶级代码在您的控制之下,您可以很容易地将循环替换为循环,直到mainloop完成循环,直到自定义协程完成。此协程将调用mainloop,然后等待清理代码完成:

代码语言:javascript
复制
# ... omitted definition of mainloop() and stop()

# list of tasks that must be waited for before we can actually exit
_cleanup = []

async def run():
    await mainloop()
    # wait for all _cleanup tasks to finish
    await asyncio.wait(_cleanup)

def handle_signal():
    # schedule stop() to run, and also add it to the list of
    # tasks run() must wait for before it is done
    _cleanup.append(loop.create_task(stop()))

loop = asyncio.get_event_loop()
loop.add_signal_handler(signal.SIGINT, handle_signal)
loop.run_until_complete(run())
loop.close()

另一种不需要新的run()协程(但仍然需要修改后的handle_signal)的选择是在mainloop完成后发出第二个run_until_complete()

代码语言:javascript
复制
# handle_signal and _cleanup defined as above

loop = asyncio.get_event_loop()
loop.add_signal_handler(signal.SIGINT, handle_signal)
loop.run_until_complete(mainloop())
if _cleanup:
    loop.run_until_complete(asyncio.wait(_cleanup))
loop.close()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48479346

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档