当我进入
asyncio
页面时,第一个示例是一个hello world程序。当我在 python 3.73
上运行它时,我看不出与正常的有什么不同。 谁能告诉我其中的区别并举一个重要的例子吗?
In [1]: import asyncio
...:
...: async def main():
...: print('Hello ...')
...: await asyncio.sleep(5)
...: print('... World!')
...:
...: # Python 3.7+
...: asyncio.run(main())
Hello ...
... World!
In [2]:
In [2]: import time
...:
...: def main():
...: print('Hello ...')
...: time.sleep(5)
...: print('... World!')
...:
...: # Python 3.7+
...: main()
Hello ...
... World!
我故意把时间从1秒增加到5秒,希望看到一些特别的东西,但我没有。
您没有看到任何特别的东西,因为您的代码中没有太多异步工作。然而,主要区别在于
time.sleep(5)
是阻塞的,而 asyncio.sleep(5)
是非阻塞的。
当调用
time.sleep(5)
时,它会阻塞脚本的整个执行,并且它会被搁置,只是冻结,什么都不做。但是当您调用 await asyncio.sleep(5)
时,它会要求事件循环在您的await 语句完成执行时运行其他内容。
这是一个改进的示例。
import asyncio
async def hello():
print('Hello ...')
await asyncio.sleep(1)
print('... World!')
async def main():
await asyncio.gather(hello(), hello())
asyncio.run(main())
将输出:
~$ python3.7 async.py
Hello ...
Hello ...
... World!
... World!
您可以看到
await asyncio.sleep(1)
并没有阻止脚本的执行。
相反,将行
await asyncio.sleep(1)
替换为 time.sleep(1)
,输出将为
Hello ...
... World!
Hello ...
... World!
因为
time.sleep
正在阻塞,并且 hello()
的第一个调用必须在 hello()
的第二个调用开始运行之前先完成。
使用下面的 time.sleep(1),首先,
test1()
每隔一秒运行一次,然后 test2()
每隔一秒运行一次:
import asyncio
import time
async def test1():
for _ in range(0, 3):
print('Test1')
time.sleep(1) # Here
async def test2():
for _ in range(0, 3):
print('Test2')
time.sleep(1) # Here
async def main():
await asyncio.gather(test1(), test2()) # Here
asyncio.run(main())
因此,运行test1()
和
test2()
总共需要6秒:
Test1 # 1 second
Test1 # 2 seconds
Test1 # 3 seconds
Test2 # 4 seconds
Test2 # 5 seconds
Test2 # 6 seconds
使用下面的 asyncio.sleep(1),
test1()
和 test2()
每隔一秒交替运行一次:
import asyncio
async def test1():
for _ in range(0, 3):
print('Test1')
await asyncio.sleep(1) # Here
async def test2():
for _ in range(0, 3):
print('Test2')
await asyncio.sleep(1) # Here
async def main():
await asyncio.gather(test1(), test2()) # Here
asyncio.run(main())
所以,总共只需要3秒来运行
test1()
和test2()
:
Test1 # 1 second
Test2 # 1 second
Test1 # 2 seconds
Test2 # 2 seconds
Test1 # 3 seconds
Test2 # 3 seconds
并且,在下面的 time.sleep(0) 中,首先,立即运行
test1()
,然后立即运行 test2()
:
import asyncio
import time
async def test1():
for _ in range(0, 3):
print('Test1')
time.sleep(0) # Here
async def test2():
for _ in range(0, 3):
print('Test2')
time.sleep(0) # Here
async def main():
await asyncio.gather(test1(), test2()) # Here
asyncio.run(main())
因此,需要0秒来运行
test1()
和test2()
总共:
Test1 # 0 second
Test1 # 0 second
Test1 # 0 second
Test2 # 0 second
Test2 # 0 second
Test2 # 0 second
并且,使用下面的 asyncio.sleep(0),
test1()
和 test2()
会同时交替运行:
import asyncio
async def test1():
for _ in range(0, 3):
print('Test1')
await asyncio.sleep(0) # Here
async def test2():
for _ in range(0, 3):
print('Test2')
await asyncio.sleep(0) # Here
async def main():
await asyncio.gather(test1(), test2()) # Here
asyncio.run(main())
因此,只需要 0 秒 即可运行
test1()
和 test2()
总共:
Test1 # 0 second
Test2 # 0 second
Test1 # 0 second
Test2 # 0 second
Test1 # 0 second
Test2 # 0 second
最后,如果没有下面的 time.sleep() 或 asyncio.sleep(),首先立即运行
test1()
,然后立即运行 test2()
:
import asyncio
async def test1():
for _ in range(0, 3):
print('Test1')
async def test2():
for _ in range(0, 3):
print('Test2')
async def main():
await asyncio.gather(test1(), test2()) # Here
asyncio.run(main())
因此,需要0秒来运行
test1()
和test2()
总共:
Test1 # 0 second
Test1 # 0 second
Test1 # 0 second
Test2 # 0 second
Test2 # 0 second
Test2 # 0 second
区别在于被阻塞的并发单位:线程与协程(异步任务)。