Python异步之asyncio
一、偏函数
如果需要减少某个函数的参数个数,可以使用 functools.partial() 。
partial() 函数允许给一个或多个参数设置固定的值,以减少接下来被调用时的参数个数。
示例1:
def spam(a, b, c, d):
print(a, b, c, d)
s1 = partial(spam, 1)
s1(2, 3, 4)
s2 = partial(spam, d=2)
s2(1, 2, 3)
运行结果
示例2:与指定点的欧几里得距离
def distance(p1, p2):
x1, y1 = p1
x2, y2 = p2
return math.hypot(x2-x1, y2-y1)
pt = (7, 4)
points = [(1, 2), (3, 4), (5, 6), (7, 8)]
points.sort(key=partial(distance, pt))
print(points)
运行结果
二、协程函数(异步函数)
1.创建协程函数
使用async关键字可将普通函数变成协程函数,即异步函数。
async def test1():
print("1")
print("2")
async def test2():
print("3")
print("4")
print(test1())
print(test2())
运行结果
除了函数外,类的方法也可以使用async关键词将其变成协程方法:
class test:
async def run(self):
pass
2.执行协程函数
async def test1():
print("1")
print("2")
async def test2():
print("3")
print("4")
a = test1()
b = test2()
try:
a.send(None)
except StopIteration as e:
print(e.value)
try:
b.send(None)
except StopIteration as e:
print(e.value)
运行结果
3.交叉执行协程函数(await)
async def test1():
print("1")
await test2()
print("2")
async def test2():
print("3")
print("4")
a = test1()
try:
a.send(None)
except StopIteration as e:
print(e.value)
运行结果
使用async可以定义协程对象,使用await可以针对耗时的操作进行挂起,就像生成器里的yield一样,函数让出控制权。
协程遇到await,事件循环将会挂起该协程,执行别的协程,直到其他的协程也挂起或者执行完毕,再进行下一个协程的执行,协程的目的也是让一些耗时的操作异步化。
注意:await后面跟的必须是一个Awaitable对象,或者实现了相应协议的对象,查看Awaitable抽象类的代码,表明了只要一个类实现了await方法,那么通过它构造出来的实例就是一个Awaitable,并且Coroutine类也继承了Awaitable。
4.自动循环执行协程函数
(1) 事件循环方法
asyncio.get_event_loop()方法
通过asyncio.get_event_loop()方法创建一个事件循环,然后使用run_until_complete()将协程注册到事件循环,并启动事件循环。
import asyncio
async def test1():
print("1")
await test2()
print("2")
async def test2():
print("3")
print("4")
loop = asyncio.get_event_loop()
loop.run_until_complete(test1())
运行结果
(2) task任务
由于协程对象不能直接运行,在注册事件循环的时候,其实是run_until_complete方法将协程包装成为了一个任务(task)对象。所谓task对象是Future类的子类,保存了协程运行后的状态,用于未来获取协程的结果。
import asyncio
async def test1():
print("1")
await test2()
print("2")
async def test2():
print("3")
print("4")
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(test1())
loop.run_until_complete(task)
print(type(task))
print(task.result())
运行结果
(3) 回调函数
在task执行完毕的时候可以获取执行的结果,回调的最后一个参数是future对象,通过该对象可以获取协程返回值。
import asyncio
async def test1():
print("1")
await test2()
print("2")
async def test2():
print("3")
print("4")
def call_back(future):
print("回调结果:", future.result())
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(test1())
task.add_done_callback(call_back)
loop.run_until_complete(task)
运行结果
网友评论