首页 > 其他分享 >协程操作

协程操作

时间:2024-04-09 20:46:03浏览次数:32  
标签:__ 协程 写入 async 操作 main asyncio

协程操作

一、asyncio模块

  • asyncio 模块是 Python 中实现异步的一个模块,该模块在 Python3.4 的时候发布
  • async 和 await 关键字在 Python3.5 中引入。
  • 因此,想要使用asyncio模块,建议 Python 解释器的版本不要低于 Python3.5 。

二、事件循环

  • 所谓的事件循环,我们可以把它当作是一个 while 循环,这个 while 循环在循环生命周期内运行并执行一些任务,在特定的条件下结束循环。
  • 在编写程序的时候可以通过如下代码来获取和创建事件循环:
import asyncio

loop = asyncio.get_event_loop()

三、协程函数和协程对象

[1]什么是协程函数

  • 简单直白地将就是在一般的函数前加上 async关键字,那这个函数就是称之为协程函数
  • 其return会默认返回调用协程函数之后的协程对象
async def func():
    ...

[2]什么是协程对象

  • 协程对象就是调用了协程函数之后返回的对象
async def func():
    ...


res = func()
# 会默认返回协程对象
print(res)  # <coroutine object func at 0x00000230E90C82E0>

四、协程函数的应用

[1]基本应用

  • 在编写程序的时候,如果想要执行协程函数内部的代码,通过 函数名() 调用函数是不可以的,需要 事件循环协程对象 配合才能实现,如下代码所示:
import asyncio


# 定义协程函数
async def func():
    print('这是协程函数内部!')

# 调用方法一
def main_first():
    # 调用协程函数产生协程对象
    res = func()

    # 生成事件
    loop = asyncio.get_event_loop()

    loop.run_until_complete(res)


if __name__ == '__main__':
    main_first()
# 这是协程函数内部!

# 调用方法二
def main_second():
    res = func()

    asyncio.run(res)

    
if __name__ == '__main__':
    main_second()
    # 这是协程函数1内部!
  • 这个过程可以简单理解为:
    • 协程函数 当做任务添加到 事件循环 的任务列表
    • 然后事件循环检测列表中的协程函数 是否已准备就绪(默认可理解为就绪状态)
    • 如果准备就绪则执行其内部代码。

[2]await关键字

  • await 是一个 只能在协程函数中使用的关键字,用于当协程函数遇到IO操作的时候挂起当前协程
  • 当前协程挂起过程中,事件循环可以去执行其他的协程
  • 当前协程IO处理完成时,可以再次切换回来执行 await 之后的代码
import asyncio
import os


async def write():
    print('写入程序开始!')
    msg = input('请输入你想要写入的信息:')
    with open(os.path.join(os.path.dirname(__file__), '信息.txt'), 'a', encoding='utf-8') as fp:
        fp.write(msg + '\n')
    return '写入成功!'


async def func():
    print('这是协程内部!')

    # 等待其他任务执行
    res = await write()

    # 打印结果
    print(res)


def main():
    res = func()

    asyncio.run(res)


if __name__ == '__main__':
    main()

"""
这是协程内部!
写入程序开始!
请输入你想要写入的信息:123
写入成功!
"""
  • 小结
    • 上述的所有实例都只是创建了一个任务
      • 即:事件循环的任务列表中只有一个任务
      • 所以在IO等待时无法演示切换到其他任务效果。
    • 在程序中想要创建多个任务对象
      • 需要使用Task对象来实现。

[3]task对象

  • Tasks 用于并发调度协程
  • 通过 asyncio.create_task(协程对象) 的方式创建 Task 对象
  • 这样可以让协程加入事件循环中等待被调度执行。
  • 除了使用 asyncio.create_task() 函数以外
  • 还可以用低层级的loop.create_task()ensure_future() 函数。并且不建议手动实例化 Task 对象。
  • 本质上是将协程对象封装成 Task 对象
  • 并将协程立即加入事件循环,同时追踪协程的状态。
  • 注意事项:
    • asyncio.create_task() 函数在 Python3.7 中被加入。
    • 在 Python3.7 之前,可以改用低层级的
    • asyncio.ensure_future() 函数。

(1)协程运行方式一

  • async.run() 运行协程
  • async.create_task()创建task
import asyncio
import os


async def write():
    print('写入程序开始!')
    msg = input('请输入你想要写入的信息:')
    with open(os.path.join(os.path.dirname(__file__), '信息.txt'), 'a', encoding='utf-8') as fp:
        fp.write(msg + '\n')
    return '写入成功!'


async def func():
    print('这是协程内部!')

    # 创建协程,将协程封装到一个Task对象中并立即添加到事件循环的任务列表中,等待事件循环去执		# 行(默认是就绪状态)。
    task = asyncio.create_task(write())

    # 使用await等待任务完成并拿到返回值
    res = await task

    # 打印返回结果
    print(res)


def main():
    asyncio.run(func())


if __name__ == '__main__':
    main()

"""
这是协程内部!
写入程序开始!
请输入你想要写入的信息:111
写入成功
"""

(2)协程运行方式二

  • asyncio.wait(Task对象列表,timeout)
  • 将创建的Task对象放入列表中,由asyncio.wait统一运行
  • asyncio.wait有两个返回值,前一个是完成的任务的返回值的集合,第二个是未完成的
import asyncio
import os


async def write():
    print('写入程序开始!')
    msg = input('请输入你想要写入的信息:')
    with open(os.path.join(os.path.dirname(__file__), '信息.txt'), 'a', encoding='utf-8') as fp:
        fp.write(msg + '\n')
    return '写入成功!'


async def func():
    print('这是协程内部!')

    # 创建协程,将协程封装到一个Task对象中并立即添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。
    task_list = [
        asyncio.create_task(write()),
        asyncio.create_task(write())
    ]

    # 使用await关键字和asyncio.wait方法等待任务完成并拿到返回值
    # asyncio.wait 会返回两个参数,完成的协程返回值写入到done中,未完成则写到pending中。
    # asyncio.wait 有timeout参数,如果设置了timeout值,则意味着此处最多等待的秒
    done, pending = await asyncio.wait(task_list)

    # 打印返回结果
    print(done)
    print(pending)


def main():
    asyncio.run(func())


if __name__ == '__main__':
    main()

r"""
这是协程内部!
写入程序开始!
请输入你想要写入的信息:11
写入程序开始!
请输入你想要写入的信息:11
{<Task finished name='Task-2' coro=<write() done, 
defined at D:\project\python\project_study\网络并发\并发编程\协程.py:223> result='写入成功!'>,
 <Task finished name='Task-3' coro=<write() done, 
 defined at D:\project\python\project_study\网络并发\并发编程\协程.py:223> result='写入成功!'>}
set()
"""

(3)获取协程返回值

  • async.gather()获取返回值
import asyncio
import os


async def write():
    print('写入程序开始!')
    msg = input('请输入你想要写入的信息:')
    with open(os.path.join(os.path.dirname(__file__), '信息.txt'), 'a', encoding='utf-8') as fp:
        fp.write(msg + '\n')
    return '写入成功!'


async def func():
    print('这是协程内部!')

    # 创建协程,将协程封装到一个Task对象中并立即添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。
    task_list = [
        asyncio.create_task(write()),
        asyncio.create_task(write())
    ]

    # 使用await关键字和asyncio.wait方法等待任务完成并拿到返回值
    # asyncio.wait 会返回两个参数,完成的协程返回值写入到done中,未完成则写到pending中。
    # asyncio.wait 有timeout参数,如果设置了timeout值,则意味着此处最多等待的秒
    res = await asyncio.gather(task_list[0], task_list[1])

    # 打印返回结果
    print(res)


def main():
    asyncio.run(func())


if __name__ == '__main__':
    main()

"""
这是协程内部!
写入程序开始!
请输入你想要写入的信息:11
写入程序开始!
请输入你想要写入的信息:11
['写入成功!', '写入成功!']
"""

[4]aiohttp对象

  • 我们之前学习过爬虫最重要的模块requests,但它是阻塞式的发起请求,每次请求发起后需阻塞等待其返回响应,不能做其他的事情。
    • 本文要介绍的aiohttp可以理解成是和requests对应Python异步网络请求库,它是基于 asyncio 的异步模块,可用于实现异步爬虫,有点就是更快于 requests 的同步爬虫。
    • 安装方式,pip install aiohttp
  • aiohttp是一个为Python提供异步HTTP 客户端/服务端编程,基于asyncio的异步库。
    • asyncio可以实现单线程并发IO操作,其实现了TCP、UDP、SSL等协议,
    • aiohttp就是基于asyncio实现的http框架。
import aiohttp
import asyncio

async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get("http://httpbin.org/headers") as response:
            print(await response.text())

asyncio.run(main())

标签:__,协程,写入,async,操作,main,asyncio
From: https://www.cnblogs.com/taoyuanshi/p/18124738

相关文章

  • 协程理论
    协程理论一、单线程下的并发本节的主题是基于单线程来实现并发即只用一个主线程(很明显可利用的CPU只有一个)情况下实现并发为此我们需要先回顾下并发的本质:切换+保存状态当CPU正在运行一个任务会在两种情况下切走去执行其他的任务该任务发生了阻塞该任务计算的时间......
  • 文档操作&异常捕获&列表、字典推导式
    【零】文档操作【1】读和写(覆盖写和追加写)#r(read):只读模式#将数据一次性全部读出#w(write):只写模式#如果文件存在则打开文件,并将文件内荣清空然后写入新的内容#如果文件不存在则新建文件,并写入新的内容#a(append):追加写模式#如果文件存在则打开文件,而......
  • 操作系统的引入
    操作系统的引入进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展开的。顾名思义,进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。所以想要真正了解进程......
  • 【Linux】编写并运行Shell脚本程序操作实例
    关于Shell脚本的介绍:Shell脚本是一种用于自动化任务和简化常见操作的脚本语言,通常用于Linux和Unix环境中。Shell脚本允许用户通过编写一系列命令和逻辑语句来执行一系列任务,从而提高了工作效率和自动化水平。以下是关于Shell脚本的详细介绍:1.基础概念:Shell本身是一个用C......
  • 机器学习&深度学习 操作tips
    1.在运行程序时,报错如下:usage:run.py[-h]--modelMODEL[--embeddingEMBEDDING][--wordWORD]run.py:error:thefollowingargumentsarerequired:--model答:出现这个问题是因为对于代码不够理解,对于在代码包中有多个models时,举例如下:不同的model类似于定义了不......
  • 使用C语言函数对数组进行操作
        前言       在我们了解数组和函数之后,我们对数组和函数进行结合,之后完成一些操作吧    题目描述    杰克想将函数与数组结合进行一些操作,以下是他想要达到的效果,请你帮帮他吧!    创建一个整型数组,完成对数组的操作   ......
  • 【C语言中的操作符详解】
    目录一 C语言中的操作符详解:1.算术操作符2.关系操作符(比较操作符)3.逻辑操作符4.位操作符5.赋值操作符6.条件(三元)操作符7.其他操作符8.递增和递减操作符二c语言操作符,应用场景:算术操作符:位操作符:关系操作符:逻辑操作符:赋值操作符:条件(三元)操作符:其他......
  • 操作系统综合题之“采用二级页表的分页存储管理方式,计算页目录号的位数 和 页的大小,给
    一、问题:某计算机系统的主存按字节编址,逻辑地址和物理地址都是32位,其内存管理采用练级页表的分页存储管理方式。逻辑地址中页号为10位,页内偏移地址为12位。该计算机系统的两级页表结构如下图所示,图中数值均为十进制数1.页目录号的位数为多少?页的大小为多少KB?2.如果页目录项大小......
  • 手写简易操作系统(二十三)--文件系统第一部分
    前情提要上面我们做好了文件系统实现的基础,现在我们开始实现文件系统。一、文件系统概念UNIX文件系统比较先进,它将文件以索引结构来组织,避免了访问某一数据块需要从头把其前所有数据块再遍历一次的缺点。采用索引结构的文件系统,文件中的块依然可以分散到不连续的零散空间......
  • 2024.4.9 avx加速一维卷积操作(汇总)
    第三次作业提交内容一:源代码在-O3编译优化下执行结果:AVX指令集优化://conv_avx.cppboolConvolve1D_Ks5_F64_AVX(double*__restrict__y,constdouble*__restrict__x,constdouble*__restrict__kernel,int64_tnum_pts){constexprint64_tkernel_size=5......