gpt4 book ai didi

python-3.x - 处理 python3 asyncio 中永不终止的任务

转载 作者:行者123 更新时间:2023-12-02 14:05:16 24 4
gpt4 key购买 nike

有时,异步任务没有有意义的终止条件 - 例如,在下面的程序中,“rate_limiter”任务在队列上以固定速率永远生成 token 流。

import asyncio
import sys

@asyncio.coroutine
def rate_limiter(queue, rate):
"""Push tokens to QUEUE at a rate of RATE per second."""
delay = 1/rate
while True:
yield from asyncio.sleep(delay)
yield from queue.put(None)

@asyncio.coroutine
def do_work(n, rate):
for i in range(n):
yield from rate.get()
sys.stdout.write("job {}\n".format(i))

def main():
loop = asyncio.get_event_loop()
rate = asyncio.Queue()
rltask = loop.create_task(rate_limiter(rate, 10))
wtask = loop.create_task(do_work(20, rate))
loop.run_until_complete(wtask)

main()

这个程序工作完美除了,asyncio 库认为在没有任何速率限制时丢弃 rltask 是一个编程错误;你会收到类似的投诉

...
job 18
job 19
Task was destroyed but it is pending!
task: <Task pending coro=<rate_limiter() running at rl.py:9>
wait_for=<Future pending cb=[Task._wakeup()]>>

(无论是否处于 Debug模式)。

我可以用类似的事件来解决这个问题,告诉 rate_limiter 协程打破它的循环,但这感觉像是额外的代码,没有真正的好处。使用 asyncio 时,您应该如何处理这种情况?

编辑:我不清楚:我正在寻找类似于线程上的daemon标志的东西:使它成为我没有的东西等待特定任务,理想情况下表示为任务本身或其协程的注释。我也接受一个表明不存在这样的机制的答案。我已经知道解决方法。

最佳答案

为了避免“任务已被销毁,但它正在挂起!”警告,如果您为相应的 future 对象设置了虚拟结果,则可以在退出程序时将永无止境的协程标记为已完成:

#!/usr/bin/env python3.5
import asyncio
import itertools
from contextlib import closing, contextmanager


@contextmanager
def finishing(coro_or_future, *, loop=None):
"""Mark a never ending coroutine or future as done on __exit__."""
fut = asyncio.ensure_future(
coro_or_future, loop=loop) # start infinite loop
try:
yield
finally:
if not fut.cancelled():
fut.set_result(None) # mark as finished


async def never_ends():
for c in itertools.cycle('\|/-'):
print(c, end='\r', flush=True)
await asyncio.sleep(.3)


with closing(asyncio.get_event_loop()) as loop, \
finishing(never_ends(), loop=loop):
loop.run_until_complete(asyncio.sleep(3)) # do something else

它假设您的协程在进程退出之前不需要显式清理。在后一种情况下,定义一个显式的清理过程:提供可以调用的方法(例如, server.close()server.wait_closed() ),或传递调用者应在关闭时设置的事件( asyncio.Event ),或引发异常(exception)(例如 CancelledError )。

引入finishing()的好处是为了检测错误,即,您不应该忽略警告,除非它被 finishing() 明确静音。打电话。

关于python-3.x - 处理 python3 asyncio 中永不终止的任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33529695/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com