协程不是系统级线程,很多时候协程被称为“轻量级线程”、“微线程”、“纤程(fiber)”等。简单来说可以认为协程是线程里不同的函数,这些函数之间可以相互快速切换。
协程和用户态线程非常接近,用户态线程之间的切换不需要陷入内核,但部分操作系统中用户态线程的切换需要内核态线程的辅助。
协程是编程语言(或者 lib)提供的特性(协程之间的切换方式与过程可以由编程人员确定),是用户态操作。协程适用于 IO 密集型的任务。常见提供原生协程支持的语言有:c++20、golang、python 等,其他语言以库的形式提供协程功能,比如 C++20 之前腾讯的 fiber 和 libco 等等。
2.1 介绍
asyncio 是用来编写并发代码的库,使用 async/await 语法。
asynci0 被用作多个提供高性能 Python 异步框架的基础,包括网络和网站服务,数据库连接库,分布式任务队列等等,asyncio 往往是构建 10 密集型和高层级 结构化 网络代码的最佳选择。
asyncio 提供一组高层级 API用于:
·并发地运行 Python 协程 并对其执行过程实现完全控制:
·执行网络 10 和 IPC:
。控制子进程:
。通过队列实现分布式任务;
·同步并发代码;
·创建和管理事件循环,以提供异步 API用于 网络化,运行 子进程,处理 OS 信号 等等
使用 transports 实现高效率协议:
·通过 async/await 语法桥接基于回调的库和代码。
1)协程通过 async/await 语法进行声明,是编写 asyncio 应用的推荐方式。
asyncio.run() 函数用来运行最高层级的入口点"main()"函数。
asyncio.sleep(delay,result=None,,loop=None) 函数用来阻塞指定的秒数。
2)事件循环函数(包括循环的创建、运行和停止)
asyncio.get _running_loop() 函数返回当前 OS 线程中正在运行的事件循环。
asyncio.get event loop()函数获取当前事件循环。
asyncio.set event loop(loop) 函数将 loop 设置为当前 OS 线程的当前事件循环。
asyncio.new_event loop() 函数创建一个新的事件循环。
loop.run until complete(future) 函数运行直到 future (Future 的实例) 被完成。
loop.run forever()函数运行事件循环直到 stop() 被调用。
loop.stop()函数停止事件循环。
loop.is_running() 函数返回 True 如果事件循环当前正在运行loop.is closed()函数如果事件循环已经被关闭,返回 True 。loop.close() 函数关闭事件循环。
loop.create future()函数创建一个附加到事件循环中的 asyncio.Future 对象。loop.create task(coro,,name=None)函数安排一个 协程 的执行。返回一个 Task 对象,loop.set task factory(factory) 函数设置一个 task 工厂,被用于 loop.create task()。loop.get task factory()函数返回一个任务工厂,或者如果是使用默认值则返回 None。
3)调度回调和延迟回调
loop.call soon(callback,args,context=None)函数安排 calback 在事件循环的下一次迭代时附带 args 参数被调用。回调按其注册顺序被调用。每个回调仅被调用一次。方法不是线程安全的。loop.call soon threadsafe(calback,args,context=None)函数是 call soon() 的线程安全变体。必须被用于安排 来自其他线程 的口调。
loop.call later(delay, callback,args, context=None) 函数安排 callback 在给定的 delay 秒(可以是 int 或者 float)后被调用。loop.call at(when, calback,args,context=None)函数安排 calback 在给定的绝对时间戳的时间(一个int 或者 foat)被调用,使用与 loop.time()同样的时间参考。
loop.time() 函数根据时间循环内部的单调时钟,返回当前时间, float 值。
socket连接和Streams函数
loop.create connection(protocol factory, host=None, port=None, , ssl=None, family=0, proto=0, flags=0, sock=None,local addr=None, server hostname=None, ssl handshake timeout=None, happy, eyeballs delay=None, interleave=None)函数打开一个流式传输连接,连接到由 host 和 port 指定的地址。
loop.create serverlprotocol factory, hostNone, port=None,, familv=socket.AF UNSPEc, flags=socke.Al PASSIVEsock=None, backlog=100,ssl=None, reuse address=None,reuse portNone,ssl handshake timeout=None.start serving=True)函数创建TCP服务 (socket 类型 SOCK STREAM)监听 host 地址的 port 端口。
loop.create unix server(protocol factory, path=None,, sock=None, backlog=100, ssl=None.ssl handshake timeouteNone, start serving=True) 函数与loop.create server)类似但是专用于 AF UNIX套接字族。path 是必要的 Unix 域套接字名称,除非提供了 sock 参数。 抽象的 Unix 套接字,str, bvtes 和 Path 路径都是受支持的。
loop.connect accepted socketlprotocol factory, sock,sslNone,ssl handshake timeout=None) 函数将已被接受的连接包装成一个传输/协议对。
loop.sock recv(sock,nbytes)函数从 sock 接收至多 nbytes。 socket.recv() 的异步版本。loop.sock recv into(sock,buf) 函数从 sock 接收数据放入 buf 缓冲区。模仿了阳塞型的 socket.recv into() 方法。loop.sock sendall(sock, data) 函数将 data 发送到 sock 套接字。 socket.sendal() 的异步版本。
loop.sock accept(sock)函数接受一个连接。 模仿了阻塞型的 socket.accept() 方法。loop.sock sendfile(sock,file, ofset=0,count=None,,fallback=True) 函数在可能的情况下使用高性能的 os.sendfile 发送文件。返回所发送的字节总数。
asyncio.open connection(host=None, port=None, , loop=None, limit=None, ssl=None, family=0, proto=0, flags=0sock=None, local addreNone, server hostname=None,ssl handshake timeout=None) 函数建立网络连接并返回一对(reader. writer)对象。
asyncio.start serverlclient connected cb, host=None, port=None., loop=None, limitNone, familv=socket.AF UNSPECflags=socketAl PASSIVE, sock=None, backlog=100,ssl=None, reuse address=None, reuse port=None.ssl handshake timeout=None,start serving=True) 函数启动套接字服务。
asyncio.open unix connection(path=None, , loop=None, limit=None, sslNone, sockeNone, server hostname=None.ssl handshake timeout=None)函数建立一个 Unix套接字连接并返回(reader, writer)这对返回值。与open connection() 相似但是操作在 Unix 套接字上。
asyncio.start unix serverlclient connected cb, path=None, , loop=None, limit=None, sock=None, backlog=100ssl=None, ssl handshake timeout=None, start serving=True)函数启动-个Unix socket服务,与 start server) 相似,但是是在 Unix 套接字上的操作。
asyncio.$treamReader 这个类表示一个提供api来从I0流中读取数据的读取器对象。
reader.read(n=-1)函数读取 n个byte.如果没有设置n,则自动置为 -1读至 EOF 并返回所有读取的byte。reader.readline() 函数读取一行,其中“行"指的是以" 结尾的字节序列。如果读到EOF而没有找到i ,该方法返回部分读取的数据。如果读到EOF,且内部缓冲区为空,则返回一个空的 bytes 对象。reader.readexactly(n)函数精准读取 n个 bytes,不能超过也不能少于reader.readuntilseparatoreb'n”函数从流中读取数据直至遇到 分隔符成功后,数据和指定的separator将从内部缓冲区中删除(或者说被消费掉)。返回的数据将包括在未尾的指定separator。如果读取的数据量超过了配置的流限制,将引发 LimitOverunError 异常,数据将留在内部缓冲区中并可以再次读取。如果在找到完整的separator之前到达EOF,则会引发 IncompleteReadEror 异常,并重置内部缓冲区。 IncompleteReadError.partial属性可能包含指定separator的一部分。reader.at eofl) 函数如果缓冲区为空并且 feed eof() 被调用,则返回 True 。
asyncio.$treamWriter 这个类表示一个写入器对象,该对象提供api以便于写数据至I0流中
writer,write(data)函数会尝试立即将 data 写入到下层的套接字。 如果写入失败,数据会被排入内部写缓冲队列直到可以被发送。writer.writelines(data)函数会立即尝试将一个字节串列表(或任何可迭代对象)写入到下层的套接字。如果写入失败,数据会被排入内部写缓冲队列直到可以被发送。
writer.close()函数会关闭流以及下层的套接字,
writer.can write eofl) 函数如果下层的传输支持 write eof() 方法则返回“True”,否则返回 False.
writer.write eof()函数在已缓冲的写入数据被刷新后关闭流的写入端。
writer.transport()函数返回下层的 asyncio 传输。
writer.drain() 函数等待直到可以适当地恢复写入到流
writer.is closing()函数如果流已被关闭或正在被关闭则返回 True。
writer.wait closed()函数等待直到流被关闭。
8)Future
asyncio.Future(,loop=None)函数是一个 Future 代表一个异步运算的最终结果。线程不安全。asyncio.isfuture(obj)函数用来判断如果 obj为一个 asyncio.Future类的示例、 asyncio.Task 类的实例或者一个具有 asyncio future blocking 属性的对象,返回 True。asyncio.ensure future(obj,,loop=None)函数创建新任务。asyncio.wrap futurelfuture.,loop=None)函数将-个 concurrent.futures.Future 对象封装到 asvncio.Future 对象中
Future 对象相关函数:
fut.result() 函数返回 Future 的结果。
fut.set result(result) 函数将 Future 标记为 完成 并设置结果。fut.set exception(exception)函数将 Future 标记为 完成 并设置一个异常。fut.done() 函数如果 Future 为已 完成 则返回 True 。fut.cancelled() 函数是如果 Future 已取消则返回 Truefut.add done callback(callback,*,context=None) 函数添加一个在 Future 完成 时运行的回调函数。fut.remove done callback(callback) 函数从回调列表中移除 callback。fut.cancel() 函数取消 Future 并调度回调函数。
fut.exception() 函数返回 Future 已设置的异常,
fut.get loop() 函数返回 Future 对象已绑定的事件循环。