python asyncio future_Asyncio 异步编程模块-Python成为专业人士笔记

专业人士笔记”系列目录:创帆云:Python成为专业人士笔记--强烈建议收藏!每日持续更新!​zhuanlan.zhihu.com

协程语法

在Python 3.5+发布之前,asyncio模块使用生成器模拟异步调用,因此具有与当前Python 3.5版本不同的语法 ;以下代码均基于python3.7

从Python 3.5开始引入了异步async及await关键字。注意,在await func()调用时无需带上括号,先感受一下如下代码:

import asyncio

async def main():

print(await func())

async def func():

# 这里可以写耗时较长的代码

return "Hello, world!"

if __name__ == "__main__":

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

事件循环EventLoop

事件循环是asyncio的核心,异步任务的运行、任务完成之后的回调、网络IO操作、子进程的运行,都是通过事件循环完成的。在python3.7中,我们甚至完全不用管事件循环,只需要使用高层API,即asyncio中的方法,我们很少直接与事件循环打交道,但是为了更加熟悉asyncio的运行原理,最好还是了解EventLoop的设计原理。

1、事件循环的创建、获取、设置

(1)asyncio.get_running_loop()。python3.7新添加的

(2)asyncio.get_event_loop()

(3)asyncio.set_event_loop(loop)

(4)asyncio.new_event_loop()

2、运行和停止事件循环

(1)loop.run_until_complete(future)。运行事件循环,直到future运行结束

(2)loop.run_forever()。在python3.7中已经取消了,表示事件循环会一直运行,直到遇到stop。

(3)loop.stop()。停止事件循环

(4)loop.is_running()。如果事件循环依然在运行,则返回True

(5)loop.is_closed()。如果事件循环已经close,则返回True

(6)loop.close()。关闭事件循环

3、创建Future和Task

(1)loop.create_future(coroutine) ,返回future对象

(2)loop.create_task(corootine) ,返回task对象

(3)loop.set_task_factory(factory)

(4)loop.get_task_factory()

4、事件循环的时钟

loop.time()。可以这么理解,事件循环内部也维护着一个时钟,可以查看事件循环现在运行的时间点是多少,就像普通的time.time()类似,它返回的是一个浮点数值,比如下面的代码。转自:https://blog.csdn.net/qq_27825451/article/details/86292513

接下来,在python云环境上运行下面的代码,实地体现一下异步程序调用:

import asyncio

async def cor1():

print("cor1 start")

for i in range(10):

await asyncio.sleep(1.5)

print("cor1", i)

async def cor2():

print("cor2 start")

for i in range(15):

await asyncio.sleep(1)

print("cor2", i)

loop = asyncio.get_event_loop()

cors = asyncio.wait([cor1(), cor2()])

loop.run_until_complete(cors)

#

cor2 start

cor1 start

cor2 0

cor1 0

cor2 1

cor1 1

cor2 2

cor2 3

cor1 2

cor2 4

cor1 3

cor2 5

cor2 6

cor1 4

cor2 7

cor1 5

cor2 8

cor2 9

cor1 6

cor2 10

cor1 7

cor2 11

cor2 12

cor1 8

cor2 13

cor1 9

cor2 14

一开始还是通过asyncio.get_event_loop()得到事件循环, 之后调用了 run_until_complete( 运行 loop ,等到 future 完成,run_until_complete 即返回 ),而调用的参数是一个 async 修饰过的函数的返回值

异步执行

asyncio 支持在异步调用任务中使用 Executor 对象 ,将Executor对象作为参数、可调用函数及其自身参数共同作为参数去调用run_in_executor() 函数来驱动异步执行事件

Executor 调度任务:

import asyncio

from concurrent.futures import ThreadPoolExecutor

def func(a, b):

# 做耗时的事情

return 'test '+a + b

async def main(loop):

executor = ThreadPoolExecutor() #初始化线程池执行器

result = await loop.run_in_executor(executor, func, "Hello", " world!")

print(result)

if __name__ == "__main__":

loop = asyncio.get_event_loop()

loop.run_until_complete(main(loop))

# 输出: test Hello world!

每个事件循环还有一个“默认”执行程序槽,可以分配给执行程序。要分配执行程序并从循环中调度任务,可以使用set default Executor()方法

import asyncio

from concurrent.futures import ThreadPoolExecutor

def func(a, b):

# 做耗时的事情

return 'test,'+a + b

async def main(loop):

# 注意:使用“None”作为第一个参数指定“默认”执行器 .

result = await loop.run_in_executor(None, func, "Hello,", " world!")

print(result)

if __name__ == "__main__":

loop = asyncio.get_event_loop()

loop.set_default_executor(ThreadPoolExecutor())

loop.run_until_complete(main(loop))

#输出 test,Hello, world!

parallel.futures中有两种主要的Executor类型,即ThreadPoolExecutor和

ProcessPoolExecutor。 ThreadPoolExecutor包含一个线程池,可以手动将其设置为通过构造函数的特定线程数,或者默认为计算机上的内核数乘以5。

ThreadPoolExecutor使用线程池执行分配给它的任务,并且通常在CPU绑定方面更好操作,而不用受I / O约束。与此形成对比的是ProcessPoolExecutor:

ProcessPoolExecutor只能接受可修改的任务和参数。最常见的非picklable任务的对象的方法。如果必须将对象的方法调度为执行程序中的任务,则必须使用ThreadPoolExecutor

UVLoop

uvloop是异步的一种实现。基于libuv的AbstractEventLoop(由nodejs使用)。它兼容99%的异步特性,并且比传统的asyncio. eventloop快得多。uvloop目前在Windows上不可用,使用前先在python云环境上用命令 python -m pip install uvloop安装它

import asyncio

import uvloop

if __name__ == "__main__":

asyncio.set_event_loop(uvloop.new_event_loop())

# 你的业务代码...

也可以通过 EventLoopPolicy 在uvloop中设置事件循环工厂 :

import asyncio

import uvloop

if __name__ == "__main__":

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

loop = asyncio.new_event_loop()

Event事件异步驱动模型

概念

可以使用event事件同步多个协程的调度

简单地说,就像一场赛跑中,一场令下枪声响起,所有赛跑者根据枪声离开起跑线,开始并行的工作

举例:

import asyncio

import functools

# 事件触发函数

def trigger(event):

print('EVENT SET')

event.set()

# 唤醒协程等待

# 事件消费者

async def consumer_a(event):

consumer_name = 'Consumer A'

print('{} waiting'.format(consumer_name))

await event.wait()

print('{} triggered'.format(consumer_name))

async def consumer_b(event):

consumer_name = 'Consumer B'

print('{} waiting'.format(consumer_name))

await event.wait()

print('{} triggered'.format(consumer_name))

# 事件

event = asyncio.Event()

# 将 coroutines 放入 future

main_future = asyncio.wait([consumer_a(event),

consumer_b(event)])

# 事件循环

event_loop = asyncio.get_event_loop()

event_loop.call_later(3, functools.partial(trigger, event)) #使用偏函数封装(详见函数式编程https://blog.csdn.net/oSuiYing12/article/details/106211761)

# 3秒后触发事件

# 完成主future

done, pending = event_loop.run_until_complete(main_future)

#输出:

Consumer B waiting

Consumer A waiting

#等待3秒后继续输出

EVENT SET

Consumer B triggered

Consumer A triggered

实现简单的Websocket

在这里,我们使用asyncio创建一个简单的 websocket。我们定义了协程以连接到服务器,并发送/接收消息。网络套接字的通信在主协程中运行,该协程由

事件循环event loop驱动:

import asyncio

import aiohttp # 需要先在云环境中安装 python -m pip install aiohttp

session = aiohttp.ClientSession()

# 处理上下文管理器

class EchoWebsocket:

async def connect(self):

self.websocket = await session.ws_connect("wss://echo.websocket.org") #建立连接的websocket服务器地址,由于在国外可能访问不到

async def send(self, message):

self.websocket.send_str(message) #发送消息函数

async def receive(self):

result = (await self.websocket.receive()) #接收消息函数

return result.data

async def main():

echo = EchoWebsocket()

await echo.connect()

await echo.send("Hello World!")

print(await echo.receive()) # 正常情况下会返回打印出"Hello World!"

if __name__ == '__main__':

# The main loop

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

以上代码均通过python3云环境测试,有问题可随时联系,请勿转载,谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python AsyncioPython 3.4 版本之后引入的一个标准库,它提供了一种异步编程的解决方案,使得 Python 开发者可以更加方便地实现高效的异步 IO 操作。相比于传统的多线程或多进程的方式,异步编程可以更好地利用 CPU 和 IO 资源,提高程序的运行效率。 以下是 Python Asyncio 的一些基本概念和用法: 1. 异步:异步指的是程序在执行 IO 操作时不会阻塞进程,而是在等待 IO 操作完成的同时可以执行其他任务。 2. 协程:协程是一种轻量级的线程,可以在一个线程中并发执行多个协程任务,从而实现异步编程。 3. 事件循环:事件循环是 Asyncio 中的核心概念,它负责调度协程任务的执行,以及处理 IO 事件。 4. FutureFutureAsyncio 中用于异步编程的一种对象,它表示一个异步操作的结果,可以用于等待异步操作的完成。 5. Task:Task 是 Future 的子类,表示一个协程任务,它封装了一个协程对象,并可以被事件循环调度执行。 以下是一个简单的使用 Asyncio 实现异步 IO 操作的例子: ```python import asyncio async def fetch_data(): print('Start fetching data...') await asyncio.sleep(1) # 模拟 IO 操作 print('Data fetched!') async def main(): task1 = asyncio.create_task(fetch_data()) task2 = asyncio.create_task(fetch_data()) await task1 await task2 asyncio.run(main()) ``` 在这个例子中,我们定义了一个 fetch_data 协程函数,它模拟了一个 IO 操作,并在操作完成后打印了一条消息。在 main 函数中,我们使用 asyncio.create_task 创建了两个任务,并等待它们的完成。由于这两个任务是并发执行的,所以它们的完成顺序是不确定的。 这只是 Asyncio 的一个简单示例,如果你想深入了解 Asyncio 的使用和原理,可以参考 Python 官方文档或者一些优秀的 Asyncio 教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值