asyncio.sleep() 与 time.sleep()

问题描述 投票:0回答:3

当我进入

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秒,希望看到一些特别的东西,但我没有。

python python-3.x asynchronous python-asyncio sleep
3个回答
224
投票

您没有看到任何特别的东西,因为您的代码中没有太多异步工作。然而,主要区别在于

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()
的第二个调用开始运行之前先完成。


12
投票

使用下面的 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

0
投票

区别在于被阻塞的并发单位:线程与协程(异步任务)。

© www.soinside.com 2019 - 2024. All rights reserved.