异步方法介绍(一)

异步方法介绍(一)

不知道小伙伴们听到异步开不开心,不管你们开不开心,反正讲这个我很爽,虽然我异步造诣不高。

我们知道大部分代码都是同步的,同步就是按照代码的逻辑顺序执行,要等上一条语句执行完了,才能执行下一条语句,这里恶心人的事情就是有些代码要等待,同步没有办法,只能等待,然后接着执行。异步就不一样了,比如这行代码要等待,不好意思,我不等你,我先做后面的事情,你什么时候完事了告诉我一下就行,可以想象到异步可以提高代码的运行效率。

有些小伙伴总喜欢把异步和多线程放在一起,我只能说它们是两种不同的概念,多线程可以简单理解为多个人做很多事情,异步可以简单理解为一个人有条理地做很多事情,一个线程的同步可以简单理解为一个简单的人傻傻地做某些事情。然后呢在python中异步写的接口和线程确实很类似,可能这也迷惑了很多人,但是它们本质上确实不一样。

异步在python中已经很多年了,但是知名度不是很高,可能大家不太习惯转变思维和用异步编程用的相对少一些,包括本人用的也比较少。异步一般是一个线程做事情,如何合理分配很重要,python中使用一个轮询机制,所有的控制都由这个调度器说了算,它会按照一定的机制反复查询,然后做出响应。

异步可以说是一系列的异步函数,至于什么是异步函数,其中细节就不深究,按照现在的标准,只要用async def声明的函数就是一个异步函数,然后在异步函数中一般要有其他的异步操作,这个时候要使用await语句来等待,看一看如何使用简单的异步函数。

""" 简单异步操作

异步过程
1.定义异步函数:async和await结合使用
2.获得轮询器:loop = asyncio.get_event_loop()
3.收集要异步的函数:tasks = [func1(), func2(), ...]
4.完成异步操作:loop.run_until_complete(asyncio.wait(tasks))
或者loop.run_until_complete(asyncio.gather(*tasks))
5.适当时候可以得到异步函数的返回值

notice:wait得到的结果是乱序的,gather得到的结果是有序的

the statistics of this file:
lines(count)    understand_level(h/m/l)    classes(count)    functions(count)    fields(count)
000000000100    ----------------------    00000000000000    0000000000000002    ~~~~~~~~~~~~~
"""

import time
import asyncio

__author__ = '与C同行'


async def wait_block_n_second(n, verbose):
    print('进入wait_block_n_second函数')
    time.sleep(n)
    print(f'{verbose}离开wait_block_n_second函数')


async def wait_noblock_n_second(n, verbose):
    print('进入wait_noblock_n_second函数')
    await asyncio.sleep(n)
    print(f'{verbose}离开wait_noblock_n_second函数')
    return n+1


if __name__ == '__main__':
    print(f'当前时间:{time.ctime()}')

    print('异步函数里没有异步操作')
    loop = asyncio.get_event_loop()
    try:
        tasks = []
        t1 = wait_block_n_second(1, '1s之后')
        t2 = wait_block_n_second(2, '2s之后')
        tasks.append(t1)
        tasks.append(t2)
        time_start_1 = time.time()
        loop.run_until_complete(asyncio.wait(tasks))
        time_end_1 = time.time()
        print(f'异步函数中没有异步操作用时:{time_end_1-time_start_1}s')
    finally:
        loop.close()

    print('异步函数中有异步操作')
    loop = asyncio.get_event_loop()
    try:
        tasks = []
        t1 = wait_noblock_n_second(2, '1s之后')
        t2 = wait_noblock_n_second(1, '2s之后')
        t3 = wait_noblock_n_second(3, '3s之后')
        t4 = wait_noblock_n_second(4, '4s之后')
        t5 = wait_noblock_n_second(6, '6s之后')
        t6 = wait_noblock_n_second(5, '5s之后')
        tasks.extend([t1, t2, t3, t4, t5, t6])
        time_start_1 = time.time()
        futures, pending = loop.run_until_complete(asyncio.wait(tasks))
        time_end_1 = time.time()
        print(f'异步函数中有异步操作用时:{time_end_1 - time_start_1}s')
        print('使用wait的到无序的结果')
        print(futures)
        print(pending)
        coro_1 = futures.pop()
        print(type(coro_1))
        print(coro_1.result())
        for i in range(5):
            coro = futures.pop()
            print(coro.result())
    finally:
        loop.close()

    print('异步函数中有异步操作')
    loop = asyncio.get_event_loop()
    try:
        tasks = []
        t1 = wait_noblock_n_second(2, '1s之后')
        t2 = wait_noblock_n_second(1, '2s之后')
        t3 = wait_noblock_n_second(3, '3s之后')
        t4 = wait_noblock_n_second(4, '4s之后')
        t5 = wait_noblock_n_second(6, '6s之后')
        t6 = wait_noblock_n_second(5, '5s之后')
        tasks.extend([t1, t2, t3, t4, t5, t6])
        time_start_1 = time.time()
        results = loop.run_until_complete(asyncio.gather(*tasks))
        time_end_1 = time.time()
        print(f'异步函数中有异步操作用时:{time_end_1 - time_start_1}s')
        print('使用gather可以顺序输出结果')
        print(results)
    finally:
        loop.close()

还记得上面讲的轮询机制吧,在代码中就是loop = asyncio.get_event_loop()这条语句,先获得一个事件循环器,然后使用loop.run_until_complete()一直监视异步函数,直到异步函数运行完成。

先看一下异步函数中没有使用await语句的等待操作:

if __name__ == '__main__':
    print(f'当前时间:{time.ctime()}')

    print('异步函数里没有异步操作')
    loop = asyncio.get_event_loop()
    try:
        tasks = []
        t1 = wait_block_n_second(1, '1s之后')
        t2 = wait_block_n_second(2, '2s之后')
        tasks.append(t1)
        tasks.append(t2)
        time_start_1 = time.time()
        loop.run_until_complete(asyncio.wait(tasks))
        time_end_1 = time.time()
        print(f'异步函数中没有异步操作用时:{time_end_1-time_start_1}s')
    finally:
        loop.close()

结果如下:
在这里插入图片描述
可以看到这样的异步函数跟同步函数运行结果没什么区别,接下来看看使用await语句的异步函数:

if __name__ == '__main__':
    print(f'当前时间:{time.ctime()}')

    print('异步函数中有异步操作')
    loop = asyncio.get_event_loop()
    try:
        tasks = []
        t1 = wait_noblock_n_second(2, '1s之后')
        t2 = wait_noblock_n_second(1, '2s之后')
        t3 = wait_noblock_n_second(3, '3s之后')
        t4 = wait_noblock_n_second(4, '4s之后')
        t5 = wait_noblock_n_second(6, '6s之后')
        t6 = wait_noblock_n_second(5, '5s之后')
        tasks.extend([t1, t2, t3, t4, t5, t6])
        time_start_1 = time.time()
        futures, pending = loop.run_until_complete(asyncio.wait(tasks))
        time_end_1 = time.time()
        print(f'异步函数中有异步操作用时:{time_end_1 - time_start_1}s')
        print('使用wait的到无序的结果')
        print(futures)
        print(pending)
        coro_1 = futures.pop()
        print(type(coro_1))
        print(coro_1.result())
        for i in range(5):
            coro = futures.pop()
            print(coro.result())
    finally:
        loop.close()

看一下结果:
在这里插入图片描述
使用await之后的异步操作将会立即执行,不会阻塞程序,同时asyncio.wait()的异步函数返回值是乱序的,最后看一下asyncio.gather()的异步函数返回值:

if __name__ == '__main__':
    print(f'当前时间:{time.ctime()}')

    print('异步函数中有异步操作')
    loop = asyncio.get_event_loop()
    try:
        tasks = []
        t1 = wait_noblock_n_second(2, '1s之后')
        t2 = wait_noblock_n_second(1, '2s之后')
        t3 = wait_noblock_n_second(3, '3s之后')
        t4 = wait_noblock_n_second(4, '4s之后')
        t5 = wait_noblock_n_second(6, '6s之后')
        t6 = wait_noblock_n_second(5, '5s之后')
        tasks.extend([t1, t2, t3, t4, t5, t6])
        time_start_1 = time.time()
        results = loop.run_until_complete(asyncio.gather(*tasks))
        time_end_1 = time.time()
        print(f'异步函数中有异步操作用时:{time_end_1 - time_start_1}s')
        print('使用gather可以顺序输出结果')
        print(results)
    finally:
        loop.close()

结果如下:
在这里插入图片描述
经过asyncio.gather()的异步函数的结果是有序的。

有没有入门异步方法,可能一次看不太懂,那就多看几次,后面再讲一些异步方法的其他方面。

喜欢python的伙伴可以关注微信公众号“与C同行”,一起进步。
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值