同步睡眠到异步协程

编程入门 行业动态 更新时间:2024-10-25 23:22:12
本文介绍了同步睡眠到异步协程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个协程如下:

async def download(): downloader = DataManager() downloader.download()

DataManager.download()方法如下:

def download(self): start_multiple_docker_containers() while True: check_containers_statuses() sleep(N) # synchronous sleep from time module

这是一个好习惯吗?如果没有,如何在 download()中使用 asyncio.sleep ?

Is this a good practice? If no, how can I use asyncio.sleep in download()?

也许这样的代码结构在概念上是错误的?

Or maybe such code structure is conceptually wrong?

推荐答案

这是我的解决方案:

import asyncio import time # Mocks of domain-specific functions # ---------------------------------- def get_container_status(container_id, initial_time): """This mocks container status to change to 'exited' in 10 seconds""" if time.time() - initial_time < 10: print("%s: container %s still running" % (time.time(), container_id)) return 'running' else: print("%s: container %s exited" % (time.time(), container_id)) return 'exited' def is_download_complete(container_id, initial_time): """This mocks download finished in 20 seconds after program's start""" if time.time() - initial_time < 20: print("%s: download from %s in progress" % (time.time(), container_id)) return False else: print("%s: download from %s done" % (time.time(), container_id)) return True def get_downloaded_data(container_id): return "foo" # Coroutines # ---------- async def container_exited(container_id, initial_time): while True: await asyncio.sleep(1) # == setTimeout(1000), != sleep(1000) if get_container_status(container_id, initial_time) == 'exited': return container_id async def download_data_by_container_id(container_id, initial_time): container_id = await container_exited(container_id, initial_time) while True: await asyncio.sleep(1) if is_download_complete(container_id, initial_time): return get_downloaded_data(container_id) # Main loop # --------- if __name__ == "__main__": initial_time = time.time() loop = asyncio.get_event_loop() tasks = [ asyncio.ensure_future(download_data_by_container_id("A", initial_time)), asyncio.ensure_future(download_data_by_container_id("B", initial_time)) ] loop.run_until_complete(asyncio.wait(tasks)) loop.close()

结果:

1487334722.321165: container A still running 1487334722.321412: container B still running 1487334723.325897: container A still running 1487334723.3259578: container B still running 1487334724.3285959: container A still running 1487334724.328662: container B still running 1487334725.3312798: container A still running 1487334725.331337: container B still running 1487334726.3340318: container A still running 1487334726.33409: container B still running 1487334727.336779: container A still running 1487334727.336842: container B still running 1487334728.339425: container A still running 1487334728.339506: container B still running 1487334729.34211: container A still running 1487334729.342168: container B still running 1487334730.3448708: container A still running 1487334730.34493: container B still running 1487334731.34754: container A exited 1487334731.347598: container B exited 1487334732.350253: download from A in progress 1487334732.3503108: download from B in progress 1487334733.354369: download from A in progress 1487334733.354424: download from B in progress 1487334734.354686: download from A in progress 1487334734.3548028: download from B in progress 1487334735.358371: download from A in progress 1487334735.358461: download from B in progress 1487334736.3610592: download from A in progress 1487334736.361115: download from B in progress 1487334737.363115: download from A in progress 1487334737.363211: download from B in progress 1487334738.3664992: download from A in progress 1487334738.36656: download from B in progress 1487334739.369131: download from A in progress 1487334739.36919: download from B in progress 1487334740.371079: download from A in progress 1487334740.37119: download from B in progress 1487334741.374521: download from A done 1487334741.3745651: download from B done

关于 sleep()函数-不,您不应该使用它.它会阻塞整个python解释器1秒钟,这不是您想要的.

As for the sleep() function - no, you shouldn't use it. It blocks the whole python interpreter for 1 second, which is not what you want.

请记住,您没有并行性(线程等),具有 concurrency .

Remember, you don't have parallelism (threads etc.), you have concurrency.

即您有一个只有1个执行线程的python解释器,您的主循环和所有协程在其中运行,相互抢占.您希望您的解释器将其工作时间的99.999%花费在由asyncio创建,轮询套接字并等待超时的主循环中.

I.e. you have a python interpreter with just 1 thread of execution, where your main loop and all your coroutines run, preempting each other. You want your interpreter to spend 99.999% of its working time in that main loop, created by asyncio, polling sockets and waiting for timeouts.

所有协程应尽快返回,并且绝对不应该包含阻塞 sleep -如果调用它,它将阻塞整个解释器并阻止主循环从套接字或运行协程获取信息响应数据,到达这些套接字.

All your coroutines should return as fast as possible and definitely shouldn't contain blocking sleep - if you call it, it blocks the whole interpreter and prevents main loop from getting information from sockets or running coroutines in response to data, arriving to those sockets.

因此,相反,您应该等待 asyncio.sleep(),它基本上等效于Javascript的 setTimeout()-它只是告诉主循环,在某些时间它应该唤醒协程并继续运行.

So, instead you should await asyncio.sleep() which is essentially equivalent to Javascript's setTimeout() - it just tells the main loop that in certain time it should wake this coroutine up and continue running it.

建议阅读:

  • snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/
  • docs.python/3/library/asyncio.html

更多推荐

同步睡眠到异步协程

本文发布于:2023-11-23 09:57:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1621023.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:睡眠

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!