为了回答您的问题,我将为同一问题提供三种不同的解决方案。
情况1:只是普通的Python
import time
def sleep():
print(f'Time: {time.time() - start:.2f}')
time.sleep(1)
def sum(name, numbers):
total = 0
for number in numbers:
print(f'Task {name}: Computing {total}+{number}')
sleep()
total += number
print(f'Task {name}: Sum = {total}\n')
start = time.time()
tasks = [
sum("A", [1, 2]),
sum("B", [1, 2, 3]),
]
end = time.time()
print(f'Time: {end-start:.2f} sec')
Output:
Task A: Computing 0+1
Time: 0.00
Task A: Computing 1+2
Time: 1.00
Task A: Sum = 3
Task B: Computing 0+1
Time: 2.01
Task B: Computing 1+2
Time: 3.01
Task B: Computing 3+3
Time: 4.01
Task B: Sum = 6
Time: 5.02 sec
情况 2:async/await 做错了
import asyncio
import time
async def sleep():
print(f'Time: {time.time() - start:.2f}')
time.sleep(1)
async def sum(name, numbers):
total = 0
for number in numbers:
print(f'Task {name}: Computing {total}+{number}')
await sleep()
total += number
print(f'Task {name}: Sum = {total}\n')
start = time.time()
loop = asyncio.get_event_loop()
tasks = [
loop.create_task(sum("A", [1, 2])),
loop.create_task(sum("B", [1, 2, 3])),
]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
end = time.time()
print(f'Time: {end-start:.2f} sec')
Output:
Task A: Computing 0+1
Time: 0.00
Task A: Computing 1+2
Time: 1.00
Task A: Sum = 3
Task B: Computing 0+1
Time: 2.01
Task B: Computing 1+2
Time: 3.01
Task B: Computing 3+3
Time: 4.01
Task B: Sum = 6
Time: 5.01 sec
案例 3:async/await 正确完成
与情况 2 相同,除了sleep
功能:
async def sleep():
print(f'Time: {time.time() - start:.2f}')
await asyncio.sleep(1)
Output:
Task A: Computing 0+1
Time: 0.00
Task B: Computing 0+1
Time: 0.00
Task A: Computing 1+2
Time: 1.00
Task B: Computing 1+2
Time: 1.00
Task A: Sum = 3
Task B: Computing 3+3
Time: 2.00
Task B: Sum = 6
Time: 3.01 sec
情况 1 和情况 2 给出相同的结果5秒,而情况 3 只是3秒。所以异步/等待正确完成是比较快的。
造成差异的原因是在实施过程中sleep
功能。
# Case 1
def sleep():
...
time.sleep(1)
# Case 2
async def sleep():
...
time.sleep(1)
# Case 3
async def sleep():
...
await asyncio.sleep(1)
在情况 1 和情况 2 中,它们是“相同的”:
他们“睡觉”,不允许其他人使用资源。
而在情况 3 中,它允许在休眠时访问资源。
在案例 2 中,我们添加了async
到正常功能。然而事件循环将运行它不间断。
为什么?因为我们没有说哪里允许循环中断你的函数来运行另一个任务。
在情况 3 中,我们准确地告诉事件循环在哪里中断函数以运行另一个任务。具体在哪里?就在这儿!
await asyncio.sleep(1)
有关这方面的更多信息,请阅读here.
考虑阅读