异步

一.协程

协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。

线程是系统级别的,它们是由操作系统调度;协程是程序级别的,由程序员根据需要自己调度。我们把一个线程中的一个个函数叫做子程序,那么子程序在执行过程中可以中断去执行别的子程序;别的子程序也可以中断回来继续执行之前的子程序,这就是协程。也就是说同一线程下的一段代码<1>执行着执行着就可以中断,然后跳去执行另一段代码,当再次回来执行代码块<1>的时候,接着从之前中断的地方开始执行。

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

1.yield实现:

yield不但可以返回一个值,它还可以接收调用者发出的参数

def consumer():
    print('开始消费了')
    ret = ''
    while True:
        producter = yield ret
        if not producter:
            return
        print('消费了%s' % producter)
        ret = '200 ok'

def produce(consu):
    # 启动生成器,第一次必须用None  <==> consumer.__next__()
    consu.send(None)
    n = 0
    while n < 5:
        n += 1
        print('生产了苹果%d' % n)
        ret = consu.send('苹果%d' % n)
        print('消费者返回:%s' % ret)
    consu.close()

c = consumer()
produce(c)

  

执行流程:
首先调用consu.send(None)启动生成器;
然后,一旦生产了东西,通过consu.send(n)切换到consumer执行;
consumer通过yield拿到消息,处理,又通过yield把结果传回;
produce拿到consumer处理的结果,继续生产下一条消息;
produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

2.其余还有第三方包greenlet和gevent实现

二.asyncio

asyncio的编程模型就是一个消息循环

import threading
import asyncio

@asyncio.coroutine
def hello():
    print('Hello world! (%s)' % threading.currentThread())
    # 模拟耗时操作
    yield from asyncio.sleep(1)
    print('Hello again! (%s)' % threading.currentThread())

# 获取EventLoop:
loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
# 执行coroutine
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

  

三.async/await

import asyncio

#async申明这是一个异步函数, await用于挂起自身,执行耗时操作
async def get():
    await asyncio.sleep(1)
    return 100

async def hello():
    print('开始了')
    # 模拟耗时操作
    a = await get()
    print('结束了%s' % a)

loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

  

四.aiohttp

aiohttp是基于asyncio实现的HTTP框架

异步简单爬虫示例:

import asyncio
import aiohttp

get_contents = []

async def html(url):
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}
    async with aiohttp.ClientSession() as session:
        async with session.get(url, headers=headers, timeout=1, verify_ssl=False) as r:
            body = await r.text()
            get_contents.append(body)


loop = asyncio.get_event_loop()
tasks = [html('http://www.baidu.com'), html('http://www.163.com')]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

print(len(get_contents))

  

输出:
2

原文地址:https://www.cnblogs.com/itfenqing/p/10275202.html