协程
(1)介绍
-
什么是协程?
- 就是在线程下面开设多线程
-
协程(Coroutines)是一种用于异步编程的概念,它是一种更轻量级的线程。协程允许程序在执行过程中暂停和恢复,从而实现非阻塞的异步编程模型
在 Python 中,协程可以使用
asyncio
模块来实现。Python 3.5 引入了async
和await
关键字,使得定义和调用协程更加方便 -
协程的优点:
- 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
- 单线程内就可以实现并发的效果,最大限度地利用cpu
- 应用程序级别速度要远远高于操作系统的切换
- 协程的缺点:
- 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
- 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程(多个任务一旦有一个阻塞没有切,整个线程都阻塞在原地,该线程内的其他的任务都不能执行了)
- 总结:
- 必须在只有一个单线程里实现并发
- 修改共享数据不需加锁
- 用户程序里自己保存多个控制流的上下文栈
- 附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))
(2)greenlet模块
greenlet
是一个用于实现协程的 Python 库,它允许在程序中创建轻量级的用户级线程,这些线程被称为 "greenlet"。每个 greenlet 都有自己的执行状态,但它们共享相同的全局解释器(GIL),因此只有一个 greenlet 能够执行 Python 代码。
from greenlet import greenlet
def foo():
print("foo start")
gr2.switch()
print("foo end")
gr2.switch()
def bar():
print("bar start")
gr1.switch()
print("bar end")
gr1 = greenlet(foo)
gr2 = greenlet(bar)
gr1.switch()
# foo start
# bar start
# foo end
# bar end
(3)asyncio模块
-
asyncio
是 Python 标准库提供的一个用于编写异步代码的模块,它提供了一种基于事件循环的异步编程模型。通过asyncio
,可以轻松编写高效的异步 I/O 代码,处理大量的并发连接和事件。 -
以下是
asyncio
的主要特点和用法:
- 事件循环(Event Loop):
asyncio
基于事件循环的模型,其中一个主要的事件循环负责调度和执行异步任务。 - 协程(Coroutines):
asyncio
使用async def
和await
关键字来定义协程,协程是一种轻量级的并发执行单元,可以在异步程序中方便地实现并发操作。 - 异步 I/O:
asyncio
提供了异步的 I/O 操作,包括文件读写、网络通信等,可以有效地处理大量的 I/O 请求。 - 并发任务:
asyncio
支持并发执行多个任务,通过asyncio.gather()
或asyncio.wait()
等函数可以同时执行多个协程任务。 - 异步上下文管理器:
asyncio
提供了异步上下文管理器,例如async with
语法,用于管理异步资源的生命周期。 - 异步事件处理:
asyncio
可以处理异步事件,例如定时器、信号等,以及与外部事件循环的集成。
(4)协程函数
- 协程函数是指使用了
async def
声明的函数,它们允许在函数内部使用await
关键字来暂停函数的执行,等待异步操作的完成,然后在操作完成后继续执行。在 Python 中,协程函数通常用于异步编程,通过asyncio
模块来实现。
async def heart():
pass
- 以下是协程函数的一些特点和用法:
- 使用 async def 定义:协程函数使用
async def
关键字来定义,例如async def heart():
- 支持 await 关键字:协程函数内部可以使用
await
关键字来暂停函数的执行,等待异步操作的完成,例如await asyncio.sleep(1)
。 - 异步执行:协程函数是异步执行的,它们可以在一个事件循环中被调度和执行,而不会阻塞程序的其他部分。
- 协程链:协程函数可以相互调用,并形成协程链,其中一个协程函数可以在等待另一个协程函数完成时暂停执行。
- 与异步上下文管理器一起使用:协程函数可以与异步上下文管理器一起使用,例如
async with
,用于管理异步资源的生命周期。
(5)协程对象
- 协程对象是通过协程函数调用而创建的对象,它表示了一个可等待的异步操作。在 Python 中,协程对象通常是使用
async def
关键字定义的协程函数所返回的。这些对象可以被用于构建异步程序,参与事件循环的调度,以及与其他协程进行协作。
async def heart():
pass
res = heart()
print(res) # <coroutine object heart at 0x000001AD87304350>
- 以下是协程对象的一些特点和用法:
- 通过协程函数创建:协程对象是通过调用使用
async def
定义的协程函数而创建的,例如coro = heart()
。 - 可等待对象:协程对象是可等待对象的一种,它可以被
await
关键字用于暂停当前协程的执行,等待其完成,例如await coro
。 - 异步调度:协程对象可以被调度到事件循环中执行,它们可以在事件循环中被等待、调度和执行。
- 状态:协程对象具有不同的状态,包括未启动(pending)、已运行(running)、已完成(done)等状态。
- 返回值:协程对象可以返回一个值,这个值可以在协程执行完成后通过
coro.result()
或者await coro
获取。
(6)基本应用
- 执行协程代码的方式一:
import asyncio
async def heart():
print(f'这是协程函数')
def main_asy():
res = heart()
pool = asyncio.get_event_loop()
pool.run_until_complete(res)
if __name__ == '__main__':
main_asy()
- 执行协程代码的方式二:
import asyncio
async def heart():
print(f'这是协程函数')
def main_async():
res = heart()
asyncio.run(res)
if __name__ == '__main__':
main_async() # 这是协程函数
(7)await关键字
-
await表示当前任务遇到阻塞需要切换
-
await
关键字是用于异步编程中的协程中的一种语法,它通常与协程对象一起使用,用于暂停当前协程的执行,等待另一个协程执行完成,并获取其结果。 -
在 Python 中,当使用
await
关键字时,Python 解释器会暂停当前协程的执行,将控制权返回给事件循环,直到等待的协程执行完成并返回结果。一旦等待的协程完成,await
表达式将返回结果,并继续执行当前协程的后续代码。 -
以下是
await
关键字的一些特点和用法:
- 用于异步上下文中:
await
关键字只能在异步上下文中使用,例如在异步函数(使用async def
定义的函数)或者异步上下文管理器中。 - 等待协程对象:
await
后面通常跟着一个协程对象,用于等待该协程执行完成,并获取其返回值。 - 暂停当前协程的执行:
await
表达式会暂停当前协程的执行,将控制权交给事件循环,直到等待的协程执行完成。 - 获取协程返回值:一旦等待的协程完成,
await
表达式将返回协程的返回值,可以将其赋值给变量或直接在表达式中使用。 - 非阻塞:与传统的同步编程中的阻塞调用不同,
await
关键字不会阻塞程序的执行,而是在等待异步操作完成时允许其他协程继续执行。
import asyncio
async def my_coroutine():
print("协程开始执行") # 打印协程开始执行的消息
await asyncio.sleep(1) # 等待1秒钟
print("协程执行完成") # 打印协程执行完成的消息
return "来自协程的问候" # 返回一个字符串
async def main():
print("主函数开始执行") # 打印主函数开始执行的消息
result = await my_coroutine() # 等待协程执行完成,并获取返回值
print("协程返回结果:", result) # 打印协程返回的结果
print("主函数执行完成") # 打印主函数执行完成的消息
asyncio.run(main()) # 运行主函数
# 主函数开始执行
# 协程开始执行
# 协程执行完成
# 协程返回结果: 来自协程的问候
# 主函数执行完成
(8)Task对象
asyncio.Task
对象是asyncio
模块中用于表示协程任务的类。它代表了一个异步操作,可以在事件循环中被调度和执行。asyncio.Task
对象与协程函数之间是一种桥梁,它允许你在事件循环中管理和调度协程的执行。- 以下是
asyncio.Task
对象的一些特点和用法:
- 创建任务:使用
asyncio.create_task()
函数或loop.create_task()
方法来创建一个asyncio.Task
对象,将一个协程函数包装成一个任务。 - 任务状态:
asyncio.Task
对象具有不同的状态,包括待运行(pending)、运行中(running)、已完成(done)等状态,可以通过task.status()
方法来获取任务的状态。 - 取消任务:可以通过调用
task.cancel()
方法来取消任务的执行,取消后任务的状态将变为已取消(cancelled),并触发相应的取消异常。 - 等待任务完成:可以使用
await task
语法或task.result()
方法来等待任务完成,并获取任务的结果。 - 异常处理:可以通过
task.exception()
方法来获取任务执行过程中的异常信息,并进行相应的处理。
import asyncio
async def my_coroutine():
print("协程开始执行")
await asyncio.sleep(1)
print("协程执行完成")
return "来自协程的问候"
async def main():
print("主函数开始执行")
task = asyncio.create_task(my_coroutine()) # 创建一个任务
print("任务对象:", task)
result = await task # 等待任务执行完成,并获取返回值
print("任务返回结果:", result)
print("主函数执行完成")
asyncio.run(main()) # 运行主函数
# 主函数开始执行
# 任务对象: <Task pending name='Task-2' coro=<my_coroutine() running at D:\2023propygo\test.py:8>>
# 协程开始执行
# 协程执行完成
# 任务返回结果: 来自协程的问候
# 主函数执行完成
(9)aiohttp对象
-
功能:
aiohttp
允许您编写异步的 HTTP 客户端和服务器,它基于 Python 的asyncio
模块,提供了高效的异步 I/O 操作。 -
用途:您可以使用
aiohttp
构建异步的 Web 服务器、Web 客户端、REST API、HTTP 代理等。 -
特点:
- 异步支持:
aiohttp
提供了异步的 HTTP 客户端和服务器,可以处理大量并发连接。 - 高性能:由于使用了异步 I/O 操作,
aiohttp
能够充分利用系统资源,提供高性能的网络通信。 - 简单易用:
aiohttp
提供了简洁的 API,易于学习和使用,同时提供了丰富的文档和示例。
- 异步支持:
-
aiohttp
模块提供了几种重要的对象,用于构建异步的 HTTP 客户端和服务器。以下是其中一些常用的对象:
aiohttp.ClientSession
:ClientSession
是用于发送 HTTP 请求的异步客户端会话对象。- 您可以使用它创建和发送 HTTP 请求,并管理请求的状态和连接池。
- 它提供了多种方法来发送 GET、POST 等类型的请求,并支持异步操作。
aiohttp.ClientResponse
:ClientResponse
是客户端接收到的 HTTP 响应对象。- 当使用
ClientSession
发送请求时,会得到一个ClientResponse
对象作为响应。 - 它包含了响应的状态码、头部信息、内容等,并提供了多种方法来读取和处理响应内容。
aiohttp.ClientRequest
:ClientRequest
是客户端发送的 HTTP 请求对象。- 当使用
ClientSession
发送请求时,会创建一个ClientRequest
对象表示待发送的请求。 - 您可以在创建请求对象时设置请求的 URL、方法、头部、数据等信息,并将其传递给
ClientSession
进行发送。
aiohttp.web.Application
:Application
是用于构建异步 Web 服务器的应用程序对象。- 您可以创建一个
Application
对象来定义路由、中间件、处理程序等,并将其运行在aiohttp.web.run_app()
函数中。
aiohttp.web.Request
和aiohttp.web.Response
**:- 这两个对象是用于处理 HTTP 请求和响应的对象,在编写
aiohttp
的 Web 服务器时经常会使用到。 Request
对象表示客户端发送的 HTTP 请求,Response
对象表示服务器返回的 HTTP 响应。
- 这两个对象是用于处理 HTTP 请求和响应的对象,在编写
-
这些对象是
aiohttp
中的核心组件,可以根据自己的需求使用它们来构建异步的 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())
标签:异步,协程,理论,await,async,执行,asyncio
From: https://www.cnblogs.com/ssrheart/p/18015833