Python asyncio异步学习笔记

2021/12/12 22:22:14

本文主要是介绍Python asyncio异步学习笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

协程

 协程不是计算机提供的机制,是程序员人为定义的。

协程被称为微线程,是一种用户态的上下文切换的技术。

简而言之就是通过一个线程实现代码块相互切换运行。

协程的意义

线程执行任务时 遇到IO耗时操作 不会再等待 而是去执行其他工作

二 实现协程的方法

1 greenlet实现协程

from greenlet import greenlet


def fun():
    print(111)
    gr2.switch()
    print(222)
    gr2.switch()


def fun1():
    print(33)
    gr1.switch()
    print(44)


gr1 = greenlet(fun)
gr2 = greenlet(fun1)

gr1.switch()

 2 yield方法

# 创建生成器函数
def fun1():
    yield 1
    yield from fun2()
    yield 2


def fun2():
    yield 3
    yield 4


f = fun1()
for item in f:
    print(item)

3 asyncio.coroutine方法 因为用的3.9版本 所以不支持 我就不写了

4async&awit关键字方法(推荐)

python3.5版本后才可以使用

import asyncio


async def func1():
    print(1)
    # 网络IO请求 下载一张图片
    await asyncio.sleep(2)  # 遇到类似IO耗时操作 自动切换到task中的其他任务
    print(2)


async def func2():
    print(33)
    # 网络IO请求 下载一张图片
    await asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到task中的其他操作
    print(444)


tasks = [asyncio.ensure_future(func2()),
         asyncio.ensure_future(func1())]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

按顺序执行 遇到耗时操作时执行其他任务

结果
33
1
444
2

三 异步编程

事件循环

理解成一个死循环,去检测并执行某些代码

# 伪代码

任务列表=[任务1,任务2,任务3]

while true:
    可执行的任务列表(比如IO请求完毕剩下其余逻辑),已完成的任务列表(任务代码全部完成) = 去任务列表中检查所有的任务 将可执行和已完成的任务返回
    
    for 可执行任务 in 可执行的任务列表:
        执行可执行的任务
    
    for 已完成的任务 in 已完成的任务列表:
        在任务列表中移除已经完成的任务

    如果任务列表中的任务都已完成 则终止循环

import asyncio

#去生成或获取一个事件循环
loop  = asynio.get_event_loop()

#将任务放到任务列表 (在任务列表中自动检测任务状态)
loop.run_util_complete(任务)

协程函数

函数名前面有async 关键字的函数

协程对象 执行协程函数得到的对象

# 协程函数
async def func():
    print (111)
# 协程对象
result = func()

协程对象的内部代码不会执行

如果要执行 需要交给事件循环来处理

import asyncio

async def func():
    print(111)
result = func()


# loop = asyncio,get_event_loop()
# loop.run_until_complete(result)
asyncio.run(result) # python3.7以后

await

await+可等待对象(协程对象,Future,Task对象-》IO等待)

import asyncio

async def func():
    print ("xxx")
    response = await asyncio.sleep(2)
    print("结束",response)

asyncio.run(func())

await 就是等待对象的值得到结果之后再继续向下走

Task对象

在事件循环中添加多个任务的。

示例1

import asyncio


async def func():
    print(111)
    await asyncio.sleep(2)
    print(222)


async def main():
    print("main开始")
    # 创建task任务 并将task 任务添加到事件循环
    task1 = asyncio.create_task(func())
    task2 = asyncio.create_task(func())

    ret1 = await task1
    ret2 = await task2
    print(ret1, ret2)


asyncio.run(main())

 示例2

import asyncio


async def func():
    print(111)
    await asyncio.sleep(2)
    print(222)


async def main():
    print("main开始")
    # 创建task任务 并将task 任务添加到事件循环
    task1 = asyncio.create_task(func(),name="task1")
    task2 = asyncio.create_task(func(),name = "task2")
    task_list = [task1, task2]
    # 返回值都放在done集合中,pending 执行过程中部分返回值放在pending中
    done, pending = await asyncio.wait(task_list)
    print(done)


asyncio.run(main())

asyncio.Future对象(了解)

task对象基于future future如果不被赋值 将一直执行不会终止 但task一般绑定一个函数,函数执行完自动赋值 也自动终止。

 Concurrent.future.Future对象

使用线程池 进程池实现异步时使用的对象

如果做异步编程时 遇到了某个第三方模块不支持协程时 使用下面这种方式

 

 异步和非异步结合案例

asyncio异步迭代器

class Reader(object):
    """自定义异步迭代器(同是也是异步可迭代对象)"""
    def __init__(self):
        self.count = 0
    async def readline(self):
        self.count +=1
        if self.count ==100:
            return None
        return self.count
    
    def__aiter__self(self):
        return self
    
    async def __anext__(self):
        val = await self.readline()
        if val == None:
            raise StopAsyncIteration
        return val
async def func():
    obj = Reader()
    #async for 循环只能在异步函数中使用 
    async for item in obj:
        print(item)
asyncio.run(func())

asyncio 异步上下文管理器

 uvloop

是asyncio循环的替代方案,事件循环>默认的asyncio的事件循环

效率提升至少一倍

 django3和fastapi内部就是使用的uvloop 所以快 支持 异步

实战案例

异步操作redis

在使用代码操作redis时,链接、操作、断开都是网络IO

同时使用两台服务器的redis 在连接第一台服务器的时候去做连接第二台服务器的任务,

异步操作mysql

 pip install aiomysql

FASTAPI框架示例

 

 爬虫示例:



这篇关于Python asyncio异步学习笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程