Python 从为回路注入a的消防协程

Python 从为回路注入a的消防协程,python,python-asyncio,coroutine,Python,Python Asyncio,Coroutine,我正试图在一个循环内启动一个协同程序。下面是一个简单的例子,说明我正在努力实现的目标: import time import random import asyncio def listen(): while True: yield random.random() time.sleep(3) async def dosomething(data: float): print("Working on data", data) asynci

我正试图在一个循环内启动一个协同程序。下面是一个简单的例子,说明我正在努力实现的目标:

import time
import random
import asyncio


def listen():
    while True:
       yield random.random()
       time.sleep(3)


async def dosomething(data: float):
    print("Working on data", data)
    asyncio.sleep(2)
    print("Processed data!")


async def main():
    for pos in listen():
        asyncio.create_task(dosomething(pos))


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
不幸的是,这不起作用,我的
dosomething
coroutine从未执行过。。。我做错了什么?

功能旨在计划任务执行,应该等待任务完成

此外,还应等待代码中的
asyncio.sleep(2)
,否则将抛出错误/警告

正确的方法:

import time
import random
import asyncio


def listen():
    while True:
       yield random.random()
       time.sleep(3)


async def dosomething(data: float):
    print("Working on data", data)
    await asyncio.sleep(2)
    print("Processed data!")


async def main():
    for pos in listen():
        await asyncio.create_task(dosomething(pos))


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
样本输出:

Working on data 0.9645515392725723
Processed data!
Working on data 0.9249656672476657
Processed data!
Working on data 0.13635467058997397
Processed data!
Working on data 0.03941252405458562
Processed data!
Working on data 0.6299882183389822
Processed data!
Working on data 0.9143748948769984
Processed data!
...

我想指出的是,在玩游戏之后,我最终使用了一个生产者、消费者架构来实现我想要的。我很感激我没有在最初的问题中明确我的确切用例。但下面是我最终实现的一个简化片段:

import asyncio
import random
from datetime import datetime
from pydantic import BaseModel


class Measurement(BaseModel):
    data: float
    time: datetime


async def measure(queue: asyncio.Queue):
    while True:
        # Replicate blocking call to recieve data
        await asyncio.sleep(1)
        print("Measurement complete!")
        for i in range(3):
            data = Measurement(
                data=random.random(),
                time=datetime.utcnow()
            )
            await queue.put(data)

    await queue.put(None)


async def process(queue: asyncio.Queue):
    while True:
        data = await queue.get()
        print(f"Got measurement! {data}")
        # Replicate pause for http request
        await asyncio.sleep(0.3)
        print("Sent data to server")


loop = asyncio.get_event_loop()
queue = asyncio.Queue(loop=loop)
meansurement = measure(queue)
processor = process(queue)
loop.run_until_complete(asyncio.gather(processor, meansurement))
loop.close()

我应该在这里指出(我不太明白的是),您发出的任何阻塞调用都必须能够
wait
-ed。否则,您可能会发现使用者将永远不会执行。

Async还会抱怨
main
在释放控制之前花费了太多时间。这只是一个警告,但在您的实际应用程序中值得考虑。谢谢@RomanPerekhrest-我正试图像在javascript>中一样使用async/await。当您除了await之外不使用task对象时,创建task是不必要的开销。您只需
等待dosomething(pos)
即可。@NickMartin注意,此代码将按顺序执行协同程序。如果您想并行执行它们,那么应该调用类似于
await asyncio.gather(*[dosomething(pos)for pos in listen()])
。此外,
listen()
应该是
async def
并使用
await asyncio.sleep()
也可以调用
time.sleep()
将继续阻止整个事件循环
main()
然后应使用
async for
对其进行迭代。