程序的执行,有同步, 有异步, 同步就是当一个任务在执行的过程中, 它会一直将这个任务执行完毕, 即使是遇到了阻塞, 也会一直干等着, 就好比你正在烧一壶水, 那么在烧水期间,你就一直干瞪眼的瞅着这壶水,直到它烧开为止, 才会去做其它事情。 这就是同步! 而异步, 是没有阻塞的概念的, 就好比在烧水的期间, 你可以去看电视,去刷抖音, 去拖地, 去做其它的事情, 而不是站在那干瞪眼瞅着水烧开。 这就是异步。
python的异步实现也是相当简单, 这里就要涉及到一个关键字 async 使用这个关键字就可以定义一个异步函数:
async def wait():
await asyncio.sleep(5)
print("等待5秒")
这里需要注意的是, 想让程序休眠就不能使用 time.sleep() 了, 因为它不是一个异步的休眠方式,无法将其挂起, 它会强制线程休眠等待, 这样就实现不了异步方案了。
import asyncio
from datetime import datetime
async def wait():
await asyncio.sleep(5)
print("等待5秒")
async def print_info(info):
print(info, datetime.now().strftime("%Y-%m-%d"))
async def main():
pass
这里又定义了两个异步函数, 其中异步main 函数就是我们的入口函数了,实现异步还有一个误区,就是在main函数中, 不要依次按顺序的去调用每个异步函数, 例如:
import asyncio
from datetime import datetime
async def wait():
await asyncio.sleep(5)
print("等待5秒")
async def print_info(info):
print(info, datetime.now().strftime("%Y-%m-%d"))
async def main():
await print_info("开始")
await wait()
await print_info("结束")
if __name__ == '__main__':
asyncio.run(main())
使用asyncio.run() 可以启动异步main函数, 但是这里有个误区, 注意看在异步main函数中, 由于我们依次调用了每个异步函数, 这样就会导致程序执行到 wait() 异步函数时候被挂起阻塞, 从而导致整个程序都是按照顺序执行的, 这样就不是异步了,而是同步了。
正确的方案应该是这样的:
一共有多种方案:
第一种:
import asyncio
from datetime import datetime
async def wait():
await asyncio.sleep(5)
print("等待5秒")
async def print_info(info):
print(info, datetime.now().strftime("%Y-%m-%d"))
async def main():
# 创建并发任务
await asyncio.gather(
print_info("开始"),
wait(),
print_info("结束")
)
if __name__ == '__main__':
asyncio.run(main())
第二种:
import asyncio
from datetime import datetime
async def wait():
await asyncio.sleep(5)
print("等待5秒")
async def print_info(info):
print(info, datetime.now().strftime("%Y-%m-%d"))
async def main():
# 创建并发任务
tasks_list = [print_info("开始"), wait(), print_info("结束")]
await asyncio.wait([asyncio.create_task(tasks) for tasks in tasks_list])
if __name__ == '__main__':
asyncio.run(main())
第三种:
import asyncio
from datetime import datetime
async def wait():
await asyncio.sleep(5)
print("等待5秒")
async def print_info(info):
print(info, datetime.now().strftime("%Y-%m-%d"))
async def main():
# 创建并发任务
tasks_list = [print_info("开始"), wait(), print_info("结束")]
for tasks in asyncio.as_completed(tasks_list):
await tasks
if __name__ == '__main__':
asyncio.run(main())
第四中, 也是最不建议的一种:
import asyncio
from datetime import datetime
async def wait():
await asyncio.sleep(5)
print("等待5秒")
async def print_info(info):
print(info, datetime.now().strftime("%Y-%m-%d"))
async def main():
# 创建异步并发任务
task1 = asyncio.create_task(print_info("开始"))
task2 = asyncio.create_task(wait())
task3 = asyncio.create_task(print_info("结束"))
await task1
await task2
await task3
if __name__ == '__main__':
asyncio.run(main())