48异步编程_asyncio_aiohttp

 

创新互联专业为企业提供老边网站建设、老边做网站、老边网站设计、老边网站制作等企业网站建设、网页设计与制作、老边企业网站模板建站服务,10余年老边做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

目录

asyncio.1

事件循环:...1

协程:...2

aiohttp:...4

 

 

 

asyncio

异步io,3.4version加入标准库;

asyncio底层基于selectors实现,看似库,其实是个框架,包含异步IO、事件循环、协程、任务等内容;

 

例:

def a():

    for x in range(3):

        time.sleep(0.001)   #生产上不能加此句,仅在多线程下做实验用

        print('a.x', x)

 

def b():

    for x in 'abc':

        time.sleep(0.001)

        print('b.x', x)

 

# a()   #串行,两件事如果有因果关系才需要串行,否则并行要好

# b()

 

# threading.Thread(target=a).start()   #多线程下,由OS控制;输出会乱

# threading.Thread(target=b).start()

 

if __name__ == '__main__':

    multiprocessing.Process(target=a).start()   #真正的同时进行,由OS控制

    multiprocessing.Process(target=b).start()

 

 

事件循环:

是asyncio提供的核心运行机制;

 

loop = asyncio.get_event_loop()   #返回一个事件循环对象,是asyncio.BaseEventLoop的实例;

loop.stop()、asyncio.AbstractEventLoop.stop()   #停止运行事件循环

loop.run_forever()、asyncio.AbstractEventLoop.run_forever()   #一直运行,直到stop

loop.run_until_complete(future)、asyncio.AbstractEventLoop.run_until_complete(future)   #运行直至Future对象运行完

loop.close()、asyncio.AbstractEventLoop.close()   #关闭事件循环

loop.is_running()、asyncio.AbstractEventLoop.is_running()   #返回事件循环是否运行

 

 

协程:

例:

协程,有返回值None,但没有用;

由自己控制(类似于并发的控制),与多线程、多进程没关系;

在线程内通过生成器完成了调度,让两个函数几乎都有在执行,这样的调度不是OS的进程、线程完成的,而是用户自己设计的;

编写此程序,要使用yield来让出控制权,要用循环帮助执行;

def a():

    for x in range(3):

        time.sleep(0.001)

        print('a.x', x)

        yield

 

def b():

    for x in 'abc':

        time.sleep(0.001)

        print('b.x', x)

        yield

 

m = a()

n = b()

for _ in range(3):

    next(m)

    next(n)

 

不是进程,也不是线程,它是用户空间调度完成并发处理的方式;

进程、线程由OS完成调度,而协程是线程内完成调度,它不需要更多的线程,自然也没有多线程切换带来的开销;

协程是非抢占式调度(串行),只有一个协程主动让出控制权,另一个协程才会被调度;

协程也需要使用锁机制,因为是在同一个线程中执行;

多cpu下,可使用多进程+协程配合,既能进程并发又能发挥协程在单线程中的优势;

py中协程是基于生成器的;

 

3.5version开始,py提供关键字async、await,在语言上原生支持协程,支持async def、async with、async for;

async def用来定义协程函数,调用后即是协程对象(同生成器函数、生成器对象),协程函数中可以不包含await、async关键字,不能使用yield关键字;

 

asyncio.iscoroutinefunction(sleep)   #判断是否是协程函数

asyncio.iscoroutine(thread)   #判断是否是协程对象

 

例:

@asyncio.coroutine   #使用装饰器,3.4ver用法

def sleep(x):   #生成器+函数(函数中有yield语句即为生成器函数)

    for i in range(3):   #有循环

        print('sleep {}'.format(i))

        yield from asyncio.sleep(x)   #asyncio.sleep(x),另一个生成器对象

 

loop = asyncio.get_event_loop()

loop.run_until_complete(sleep(10))   #sleep(3)必须要有括号,sleep为生成器函数,可理解为拿到生成器对象,用返回的对象循环

loop.close()

 

例:

asyncdef sleep(x):   #3.5ver用法

    for i in range(3):

        print('sleep {}'.format(i))

        await asyncio.sleep(x)

 

async def showthread(x):

    for i in range(3):

        print(threading.enumerate())

        await asyncio.sleep(x)

 

loop = asyncio.get_event_loop()

tasks = [sleep(3), showthread(3)]   #放协程对象

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

 

print(asyncio.iscoroutinefunction(sleep))

print(asyncio.iscoroutine(showthread))

输出:

[<_MainThread(MainThread, started 19172)>]

sleep 0

[<_MainThread(MainThread, started 19172)>]

sleep 1

[<_MainThread(MainThread, started 19172)>]

sleep 2

True

False

 

例:

TcpEchoServer

 

 

aiohttp:

>pip install aiohttp

 

对于socket,在accept()后,关键是recv()和send();

对于http,关键是request和response;

 

异步的好处:

没有多线程,并发用多进程;

多进程 + 协程,可完成很高的并发;

 

简单函数-->多线程-->IO复用-->异步io;

 

例,服务端:

from aiohttp import web

 

async def indexhandle(request: web.Request):

    return web.Response(text=request.path, status=201)

 

async def handle(request: web.Request):

    print(request.match_info)

    print(request.query_string)

    return web.Response(status=200,text=request.match_info.get('id', '0000'))

 

app = web.Application()

app.router.add_get('/', indexhandle)

app.router.add_get('/{id}', handle)

web.run_app(app, host='0.0.0.0', port=9999)

输出:

======== Running on http://0.0.0.0:9999 ========

(Press CTRL+C to quit)

-> >

 

 

例,客户端:

from aiohttp import ClientSession

import asyncio

 

async def get_html(url: str):

    async with ClientSession() as session:   #client与server建立会话

        async with session.get(url) as res:   #response

            print(res.status)

            print(await res.text())

 

url = 'http://127.0.0.1:9999/555'   #服务端

 

loop = asyncio.get_event_loop()

loop.run_until_complete(get_html(url))   #爬虫的第一步,拿到html页面数据后,用第三方库解析html变成dom树,拿到想要的东西

loop.close()

输出:

200

555

 


新闻名称:48异步编程_asyncio_aiohttp
当前地址:http://ybzwz.com/article/ppedgj.html