使用asyncio做多项终极工作
Use asyncio to do multiple ultimate jobs
有2个工作:"wash_clothes"(job1)和"setup_cleaning_robot"(job2),每个工作需要你7秒3秒,你必须做到世界末日。
这是我的代码:
import asyncio
async def wash_clothes():
print(f'Start job1')
await asyncio.sleep(3)
print(f'Finish job1, took 3 seconds')
async def setup_cleaning_robot():
print(f'Start job2')
await asyncio.sleep(7)
print(f'Finish job2, took 7 seconds')
async def not_really_asyncio():
kk = 1
while True:
job_list = [wash_clothes(), setup_robot()]
await asyncio.gather(*job_list)
kk += 1
async def main():
await not_really_asyncio()
# await really_asyncio() # Still don't know how to do
if __name__ == '__main__':
asyncio.run(main())
这是输出
Start job1
Start job2
Finish job1, took 3 seconds
Finish job2, took 7 seconds
Start job1
Start job2
Finish job1, took 3 seconds
Finish job2, took 7 seconds
...
...
但我们知道我们可以放衣服,然后安装清洁机器人,休息一下(只有几秒钟),直到其中一项工作完成,然后现在就做,一次又一次.. .
正确的输出如下:
Start job1
Start job2
Finish job1, took 3 seconds
Start job1
Finish job1, took 3 seconds
Start job1
Finish job2, took 7 seconds
Start job2
Finish job1, took 3 seconds
...
...
目前我有使用线程的想法,但它会弄乱我的代码。
我希望代码尽可能简洁
最短的方法是:
# ...
async def constantly_wash_clothes():
while True:
await wash_clothes()
async def constantly_setup_cleaning_robot():
while True:
await setup_cleaning_robot()
async def main():
await asyncio.gather(
constantly_wash_clothes(),
constantly_setup_cleaning_robot()
)
if __name__ == '__main__':
asyncio.run(main())
它会给你想要的输出。
您想要但当前代码中没有发生的关键事情是,当洗完衣服后,您立即再次开始洗衣服,即使清洁机器人还在进度(并将再持续 4 秒)。但是这里的这一行阻止了:
async def not_really_asyncio():
kk = 1
while True:
job_list = [wash_clothes(), setup_robot()]
await asyncio.gather(*job_list) # <--- Waits until *both* finish
kk += 1
asyncio.gather
等待所有作业完成。所以即使 wash_clothes
已经完成,gather
也会继续坐在那里等待 setup_robot
也完成。
我可以想出两种方法来解决这个问题。
在while
循环中,使用asyncio.wait()
代替gather
。这允许您等到只有一个任务完成,此时您可以立即启动它的另一个实例。
这是修复您的代码当前所做的最直接的方法。然而,它非常棘手:asyncio.wait()
非常繁琐(它的参数是任务而不是协程,你必须分开它的 return 值)并且你的 while
循环将必须 运行 仅那些尚未 运行ning.
的任务
一个更横向的想法是为两个任务中的每一个使用单独的while
循环。您可以将它们放在单独的函数中或直接放在 wash_clothes()
和 setup_cleaning_robot()
函数中。
像这样:
counter = 0
async def keep_washing_clothes():
while True:
await wash_clothes()
global counter
counter += 1
async def keep_setting_up_cleaning_robot():
while True:
await setup_cleaning_robot()
global counter
counter += 1
async def really_asyncio():
job_list = [keep_washing_clothes(), keep_setting_up_cleaning_robot()]
await asyncio.gather(*job_list)
奖金聊天 如果将时间戳记放在 print()
输出中,您可能会发现更容易理解发生了什么:
# At the start of your script:
from datetime import datetime
# Later on:
print(datetime.utcnow().isoformat(), 'Finish job2, took 7 seconds')
有2个工作:"wash_clothes"(job1)和"setup_cleaning_robot"(job2),每个工作需要你7秒3秒,你必须做到世界末日。
这是我的代码:
import asyncio
async def wash_clothes():
print(f'Start job1')
await asyncio.sleep(3)
print(f'Finish job1, took 3 seconds')
async def setup_cleaning_robot():
print(f'Start job2')
await asyncio.sleep(7)
print(f'Finish job2, took 7 seconds')
async def not_really_asyncio():
kk = 1
while True:
job_list = [wash_clothes(), setup_robot()]
await asyncio.gather(*job_list)
kk += 1
async def main():
await not_really_asyncio()
# await really_asyncio() # Still don't know how to do
if __name__ == '__main__':
asyncio.run(main())
这是输出
Start job1
Start job2
Finish job1, took 3 seconds
Finish job2, took 7 seconds
Start job1
Start job2
Finish job1, took 3 seconds
Finish job2, took 7 seconds
...
...
但我们知道我们可以放衣服,然后安装清洁机器人,休息一下(只有几秒钟),直到其中一项工作完成,然后现在就做,一次又一次.. .
正确的输出如下:
Start job1
Start job2
Finish job1, took 3 seconds
Start job1
Finish job1, took 3 seconds
Start job1
Finish job2, took 7 seconds
Start job2
Finish job1, took 3 seconds
...
...
目前我有使用线程的想法,但它会弄乱我的代码。
我希望代码尽可能简洁
最短的方法是:
# ...
async def constantly_wash_clothes():
while True:
await wash_clothes()
async def constantly_setup_cleaning_robot():
while True:
await setup_cleaning_robot()
async def main():
await asyncio.gather(
constantly_wash_clothes(),
constantly_setup_cleaning_robot()
)
if __name__ == '__main__':
asyncio.run(main())
它会给你想要的输出。
您想要但当前代码中没有发生的关键事情是,当洗完衣服后,您立即再次开始洗衣服,即使清洁机器人还在进度(并将再持续 4 秒)。但是这里的这一行阻止了:
async def not_really_asyncio():
kk = 1
while True:
job_list = [wash_clothes(), setup_robot()]
await asyncio.gather(*job_list) # <--- Waits until *both* finish
kk += 1
asyncio.gather
等待所有作业完成。所以即使 wash_clothes
已经完成,gather
也会继续坐在那里等待 setup_robot
也完成。
我可以想出两种方法来解决这个问题。
在
while
循环中,使用asyncio.wait()
代替gather
。这允许您等到只有一个任务完成,此时您可以立即启动它的另一个实例。这是修复您的代码当前所做的最直接的方法。然而,它非常棘手:
asyncio.wait()
非常繁琐(它的参数是任务而不是协程,你必须分开它的 return 值)并且你的while
循环将必须 运行 仅那些尚未 运行ning. 的任务
一个更横向的想法是为两个任务中的每一个使用单独的
while
循环。您可以将它们放在单独的函数中或直接放在wash_clothes()
和setup_cleaning_robot()
函数中。
像这样:
counter = 0
async def keep_washing_clothes():
while True:
await wash_clothes()
global counter
counter += 1
async def keep_setting_up_cleaning_robot():
while True:
await setup_cleaning_robot()
global counter
counter += 1
async def really_asyncio():
job_list = [keep_washing_clothes(), keep_setting_up_cleaning_robot()]
await asyncio.gather(*job_list)
奖金聊天 如果将时间戳记放在 print()
输出中,您可能会发现更容易理解发生了什么:
# At the start of your script:
from datetime import datetime
# Later on:
print(datetime.utcnow().isoformat(), 'Finish job2, took 7 seconds')