python中asyncio模块

3.4版本加入标准库
asyncio底层属于selectors实现,看似库,其实是个框架,包含异步IO、事件循环、协程、任务等内容

  • 这是一个串行的程序,是一个单线程
def a():
    for x in range(3):
        print(x)
def b():
    for x in "abc":
        print(x)
a()
b()

在这里插入图片描述

  • 多线程版本
import threading
import time

def a():
    for x in range(3):
        time.sleep(0.001)
        print(x)
def b():
    for x in "abc":
        time.sleep(0.001)
        print(x)
threading.Thread(target=a,name='a').start()
threading.Thread(target=b,name='b').start()

在这里插入图片描述

  • 多进程版本
import multiprocessing
import time

def a():
    for x in range(3):
        time.sleep(0.001)
        print(x)
def b():
    for x in "abc":
        time.sleep(0.001)
        print(x)
if __name__=="__main__":
    multiprocessing.Process(target=a,name='a').start()
    multiprocessing.Process(target=b,name='b').start()

在这里插入图片描述

  • 生成器
def a():
    for x in range(3):
        print(x)
        yield
def b():
    for x in "abc":
        print(x)
        yield
x=a()
y=b()
for _ in range(3):
    next(x)
    next(y)

在这里插入图片描述
上例在一个线程内通过生成器完成了调度,让两个函数都有机会执行,这样的调度不是操作系统的进程、线程完成的,而是用户自己设计出来的

事件循环

事件循环是asyncio提供的核心运行机制

columncolumn
asyncio.get_evebt_loop()返回一个事件循环对象,是asyncio.BaseEventLoop的实例
AbstractEventLoop.stop()停止运行事件循环
AbstractEventLoop.run_forever()一直运行,直到stop()
AbstractEventLoop.run_until_complete(future)运行直至Future运行完,返回Future的结果,参数可以是Future类或子类Task的对象。如果是协程对象也会被封装成Task对象
AbstractEventLoop.close()关闭事件循环
AbstractEventLoop.is_running()返回事件循环的是否运行
AbstractEventLoop.close()关闭事件循环
AbstractEventLoop.create_task(coro)使用协程对象创建任务对象
协程
  • 协程不是进程、也不是线程,它是用户空间调度的按成并发处理的方式
  • 进程、线程由操作系统完成调度,而协程是线程内完成调度,它不需要更多的线程,自然也没有多线程切换带来的开销
  • 协程是非抢占式调度,只有一个协程主动让出控制权,另一个协程才会被调度
  • 协程也不需要使用锁机制,因为是在同一个线程中执行
  • 多CPU下,可以使用多进程和协程配合,既能进程并发又能发挥协程在单线程中的优势
  • Python中协程是基于生成器的
  • asyncio.iscoroutine(obj)判断是不是协程对象
  • asyncio.iscoroutinefunction(func)判断是不是协程函数
    Future:coucurrent.futures.Future类似,通过Future对象可以了解人物执行的状态数据。事件循环来监控Future对象是否完成。
    Task任务:Task类是Future的子类,它的作用就是把协程包装成一个Future对象。
import asyncio

@asyncio.coroutine
def sleep(x):
    for i in range(3):
        print("sleep----{}".format(i))
        yield from asyncio.sleep(x)
    return "result-{}".format(1000)
#事件循环
loop=asyncio.get_event_loop()
#本质就是tasks的ensure_future,把协程包装进一个Future对象中,并使用create_task返回一个task
future=asyncio.ensure_future(sleep(3))
# 内部会调用ensure_future,内部会执行loop.run_forever
loop.run_until_complete(future)

loop.close()
print(future.result())

在这里插入图片描述
ensure_future(coro_or_future)
如果参数已经是future直接返回
如果是协程,则使用loop.create_task()创建task,并返回task
可以使用create_task得到task对象

import asyncio

@asyncio.coroutine
def sleep(x):
    for i in range(3):
        print("sleep----{}".format(i))
        yield from asyncio.sleep(x)
    return "result-{}".format(1000)
#事件循环
loop=asyncio.get_event_loop()
#本质就是tasks的ensure_future,把协程包装进一个Future对象中,并使用create_task返回一个task
task=loop.create_task(sleep(3))
# 内部会调用ensure_future,内部会执行loop.run_forever
loop.run_until_complete(task)

loop.close()
print(task.result())

在这里插入图片描述
还可以写成

import asyncio

@asyncio.coroutine
def sleep(x):
    for i in range(3):
        print("sleep----{}".format(i))
        yield from asyncio.sleep(x)
    return "result-{}".format(1000)
#事件循环
loop=asyncio.get_event_loop()
#本质就是tasks的ensure_future,把协程包装进一个Future对象中,并使用create_task返回一个task
# 内部会调用ensure_future,内部会执行loop.run_forever
loop.run_until_complete(sleep(3))

loop.close()

在这里插入图片描述

回调的使用

上例中,似乎拿不到sleep(3)这个协程对象的结果future了,run_until_complete函数的返回值就是其参数future对象的返回结果。
future对象都可以调用add_done_callback(fn)增加回调函数,回调函数是单参的,参数就是future对象。

import asyncio

@asyncio.coroutine
def sleep(x):
    for i in range(3):
        print("sleep----{}".format(i))
        yield from asyncio.sleep(x)
    return "result-{}".format(1000)
#回调函数,参数必须是future
def cb(future):
    print("this is future",future)
    print(future.result())
loop=asyncio.get_event_loop()
#create_task返回一个task
task=loop.create_task(sleep(3))
task.add_done_callback(cb)
loop.run_until_complete(task)
loop.close()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值