学Python不得不掌握的库,gevent和asyncio使用方法详解

一、gevent

在这里插入图片描述

python程序实现的一种单线程下的多任务执行调度器,简单来说在一个线程里,先后执行AB两个任务,但是当A遇到耗时操作(网络等待、文件读写等),这个时候gevent会让A继续执行,但是同时也会开始执行B任务,如果B在遇到耗时操作同时A又执行完了耗时操作,gevent又继续执行A。

使用示例:

import gevent
def test(time):

    print(1)

    gevent.sleep(time)

    print(2)
def test2(time):

    print(3)

    gevent.sleep(time)

    print(4)
if __name__ == '__main__':

    gevent.joinall([

        gevent.spawn(test, 2),

        gevent.spawn(test2, 3)

    ])
----------------------------------

1

3

2

4

其中gevent.sleep()是gevent自带的延时,当gevent遇到这个延时时会自动切换,这里用gevent.sleep()代替一些耗时操作,如数据库的读写、http请求、文件度写等操作,gevent给我们提供了一个很简单的协程操作。

二、asyncio

asyncio的使用上,感觉和gevent有异曲同工之妙

1、基础概念:

event_loop 事件循环:理解为一个循环的池,里面存放一些async关键词定义的协程函数,只有放到循环池里才能执行

coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。

task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。

future:代表将来执行或没有执行的任务的结果。它和task上没有本质的区别

async/await 关键字:python3.5 用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。

import time

import asyncio
now = lambda : time.time()
async def do_some_work(x):    # 使用async关键字定义协程
    print('Waiting: ', x)
start = now()
coroutine = do_some_work(2)     # 创建协程对象
loop = asyncio.get_event_loop()    # 创建一个事件循环(池)
loop.run_until_complete(coroutine)    # 将协程对象包装并注册协程对象

2
Waiting:  2
TIME:  0.0004658699035644531

2、创建task

协程对象不能直接运行,需要包装成任务才能运行,上面是通过run_until_complete()方法包装成task(隐式包装),还有下面两种方式进行显式包装:

import asyncio
import time
now = lambda : time.time()
async def do_some_work(x):
    print('Waiting: ', x)
start = now()
coroutine = do_some_work(2)
loop = asyncio.get_event_loop()
# task = asyncio.ensure_future(coroutine)    # 方式一
task = loop.create_task(coroutine)    # 方式二
print(task)
loop.run_until_complete(task)
print(task)
print('TIME: ', now() - start)
2
3
4
<Task pending coro=<do_some_work() running at /Users/ghost/Rsj217/python3.6/async/async-main.py:17>>
Waiting:  2
<Task finished coro=<do_some_work() done, defined at /Users/ghost/Rsj217/python3.6/async/async-main.py:17> result=None>
TIME:  0.0003490447998046875

创建task后,task在加入事件循环之前是pending状态,加入loop后运行中是running状态,loop调用完是Done,运行完是finished状态,虽说本质上协程函数和task指的东西都一样,但是task有了协程函数的状态。

其中loop.run_until_complete()接受一个future参数,futurn具体指代一个协程函数,而task是future的子类,所以我们不声明一个task直接传入协程函数也能执行。

3、绑定回调函数

通过task的task.add_done_callback(callback)方法绑定回调函数,回调函数接收一个future对象参数如task,在内部通过future.result()获得协程函数的返回值。

import asyncio
async def test(x):
    return x+3
def callback(y):
    print(y.result())
coroutine = test(5)
loop = asyncio.get_event_loop()
task = loop.create_task(coroutine)
task
<Task pending coro=<test() running at <ipython-input-4-61142fef17d8>:1>>
task.add_done_callback(callback)
loop.run_until_complete(task)

Out[10]: 8

或者直接通过下面方式也能获取反馈结果

task.result()
4、await(挂起耗时操作)

多任务声明了协程函数,也同时在loop中注册了,他的执行也是顺序执行的,因为在异步函数中没有声明那些操作是耗时操作,所以会顺序执行。await的作用就是告诉控制器这个步骤是耗时的,async可以定义协程对象,使用await可以针对耗时的操作进行挂起

import asyncio
import time
async def test(1):
    time.sleep(1)
    print(time.time())
tasks = [asyncio.ensure_future(test()) for _ in range(3)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

1547187398.7611663
1547187399.7611988
1547187400.7632194


Out[8]: 
({<Task finished coro=<test() done, defined at <ipython-input-5-1534f9ca2d8e>:4> result=None>,
  <Task finished coro=<test() done, defined at <ipython-input-5-1534f9ca2d8e>:4> result=None>,
  <Task finished coro=<test() done, defined at <ipython-input-5-1534f9ca2d8e>:4> result=None>},
 set())

上面执行并不是异步执行,而是顺序执行,但是改成下面形式那就是异步执行:

import asyncio
import time
async def test(t):
    await asyncio.sleep(1)
    print(time.time())
tasks = [asyncio.ensure_future(test()) for _ in range(3)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

1547187398.7611663
1547187399.7611988
1547187400.7632194
Out[11]: 
({<Task finished coro=<test() done, defined at <ipython-input-9-3a874803716b>:4> result=None>,
  <Task finished coro=<test() done, defined at <ipython-input-9-3a874803716b>:4> result=None>,
  <Task finished coro=<test() done, defined at <ipython-input-9-3a874803716b>:4> result=None>},
 set())

可见三个任务的间隔时间几乎忽略不计,这里要注意可以使用await成功挂起的对应应该是下面三种:

原生异步函数(coroutine )
由 types.coroutine() 修饰的生成器,这个生成器可以返回 coroutine 对象。
包含 __await 方法的对象返回的一个迭代器
所以即使使用saync修饰requests的方法也不支持异步,而是需要专门的异步网络请求库aiohttp。

5、aiohttp

aiohttp需要单独安装,然后和asyncio库一起使用,看一下案例

async def get(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            print(response)
            print(time.time())

import time
async def request():
    url = "http://www.baidu.com"
    resulit = await get(url)

tasks = [asyncio.ensure_future(request()) for _ in range(10)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))


<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0x94343a8f0000d2ac', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+fcb1f5fc4ea50a8475457d9dba4ffb75', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:19:54 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD4059F7858332E63E4CA:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD4059F7858332E63E4CA; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=26525_1426_21079_28132_28266; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.4161415
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0xb19b30e80000e08d', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+6035b8e98737e4cc11dcc73ec79566cc', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:19:48 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD405C594443631339D6D:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD405C594443631339D6D; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=26522_1423_21104_28132_28267_22158; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.417142
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0xfdf776e30000dfb4', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+0810232ebbebf660004801978cbc7056', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:20:15 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD40584DF85554050AB79:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD40584DF85554050AB79; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=1465_21118_28131_28267_20718; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.4221385
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0x879158430000a46a', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+acdef638e6acee7494d7fce1008c87ca', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:20:03 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD40593C8E085477DD125:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD40593C8E085477DD125; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=1448_21109_28131_28267; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.424138
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0xe5c481900000cd70', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+fb1596a42119b92bcb6a321cfd1bde58', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:19:51 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD405BD554041F5821AB7:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD405BD554041F5821AB7; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=1448_21105_18560_28132_28266_20719; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.4261389
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0x85ab35690000c4fd', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+15e5fc3bd83c4ffcdf9698e3264f7621', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:20:00 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD405C594443631339D6D:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD405C594443631339D6D; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=26522_1423_21104_28132_28267_22158; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.428144
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0x9620ed6b0000f26c', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+a2bfd2645e7c3d7514192a060f9644f5', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:20:12 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD4055EFEDF62083FAFD3:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD4055EFEDF62083FAFD3; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=1427_21127_28132_28267; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.4291408
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0x912a1be40000e841', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+599a770e18be144be77bd13c371daf0a', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:20:35 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD405106191D066098188:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD405106191D066098188; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=1424_21111_28132_28266; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.4311435
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0x943943940000b92b', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+17014bf10c56f72b235b529f8f9c177b', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:20:31 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD40504EF38ED596AEC59:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD40504EF38ED596AEC59; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=1446_21118_28131_26350_28267_22158; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.4331403
<ClientResponse(http://www.baidu.com) [200 OK]>
<CIMultiDictProxy('Bdpagetype': '1', 'Bdqid': '0xfd3e1b1f0000d880', 'Cache-Control': 'private', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Cxy_all': 'baidu+39d965c50587bb578c5714a0d732b2e4', 'Date': 'Fri, 11 Jan 2019 07:20:37 GMT', 'Expires': 'Fri, 11 Jan 2019 07:20:25 GMT', 'P3p': 'CP=" OTI DSP COR IVA OUR IND COM "', 'Server': 'BWS/1.1', 'Set-Cookie': 'BAIDUID=76DA9E559DEFD4059A93CF4E300A8EEB:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'BIDUPSID=76DA9E559DEFD4059A93CF4E300A8EEB; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'PSTM=1547191237; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com', 'Set-Cookie': 'delPer=0; path=/; domain=.baidu.com', 'Set-Cookie': 'BDSVRTM=0; path=/', 'Set-Cookie': 'BD_HOME=0; path=/', 'Set-Cookie': 'H_PS_PSSID=1445_21113_28131_28267_22158; path=/; domain=.baidu.com', 'Vary': 'Accept-Encoding', 'X-Ua-Compatible': 'IE=Edge,chrome=1', 'Transfer-Encoding': 'chunked')>
1547191237.4341416

几个任务的时间之差基本忽略不计,那亲测发送一千个请求也就11秒完成,确实很给力。

6、多进程配合使用

asyncio、aiohttp需要配合aiomultiprocess库使用,版本要求至少3.6,贴上该库的github上的使用示例,目前还在验证:

Usage
Most of aiomultiprocess mimics the standard multiprocessing module whenever possible, while accounting for places that benefit from async functionality.

Executing a coroutine on a child process is as simple as:

import asyncio
from aiohttp import request
from aiomultiprocess import Process

async def put(url, params):
    async with request("PUT", url, params=params) as response:
        pass

async def main():
    p = Process(target=put, args=("https://jreese.sh", ))
    await p

asyncio.run(main())
If you want to get results back from that coroutine, Worker makes that available:

import asyncio
from aiohttp import request
from aiomultiprocess import Worker

async def get(url):
    async with request("GET", url) as response:
        return await response.text("utf-8")

async def main():
    p = Worker(target=get, args=("https://jreese.sh", ))
    response = await p

asyncio.run(main())
If you want a managed pool of worker processes, then use Pool:

import asyncio
from aiohttp import request
from aiomultiprocess import Pool

async def get(url):
    async with request("GET", url) as response:
        return await response.text("utf-8")

async def main():
    urls = ["https://jreese.sh", ...]
    async with Pool() as pool:
        result = await pool.map(get, urls)

asyncio.run(main())

7、多协程并发

使用loop.run_until_complete(syncio.wait(tasks)) 也可以使用 loop.run_until_complete(asyncio.gather(*tasks)) ,前者传入task列表,会对task进行解包操作。

7、协程嵌套

顾名思义是一个协程中调用另一个协程,但是涉及到两个协程函数的结果处理和返回。

async def get(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            print(response)
            print(time.time())

import time
async def request():
    url = "http://www.baidu.com"
    resulit = await get(url)

tasks = [asyncio.ensure_future(request()) for _ in range(10000)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

被调用协程返回结果有下列三种方式;

async def get(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            print(response)
            print(time.time())
async def request():
    url = "http://www.baidu.com"
    tasks = [asyncio.ensure_future(url) for _ in range(1000)]
方式一:
    dones, pendings = await asyncio.wait(tasks) # 返回future对象,不返回直接结果
    for task in dones:
        print('Task ret: ', task.result())
方式二:
    results = await asyncio.gather(*tasks) # 直接返回结果

方式三:
    for task in asyncio.as_completed(tasks):
        result = await task
        print('Task ret: {}'.format(result)) # 迭代方式返回结果

tasks = asyncio.ensure_future(request())
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

8、停止协程任务

实现结束task有两种方式:关闭单个task、关闭loop,涉及主要函数:

asyncio.Task.all_tasks()获取事件循环任务列表

KeyboardInterrupt捕获停止异常(Ctrl+C)

loop.stop()停止任务循环

task.cancel()取消单个任务

loop.run_forever()

loop.close()关闭事件循环,不然会重启

重启

方式一:适用于内嵌协程函数,先取内嵌协程任务

async def get(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
print(response)
print(time.time())
async def request():
url = "http://www.baidu.com"
tasks = [asyncio.ensure_future(url) for _ in range(1000)]
dones, pendings = await asyncio.wait(tasks)

task = asyncio.ensure_future(request())
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(task)
except KeyboardInterrupt as e:
asyncio.gather(*asyncio.Task.all_tasks()).cancel()
loop.stop()
loop.run_forever()
finally:
loop.close()

方式二:适用于无内嵌函数,直接遍历协程任务

loop = asyncio.get_event_loop()
try:
loop.run_until_complete(asyncio.wait(tasks))
except KeyboardInterrupt as e:
for task in asyncio.Task.all_tasks():
print(task.cancel())
loop.stop()
loop.run_forever()
finally:
loop.close()

ID:Python之战

|作|者|公(zhong)号:python之战

专注Python,专注于网络爬虫、RPA的学习-践行-总结

喜欢研究技术瓶颈并分享,欢迎围观,共同学习。

独学而无友,则孤陋而寡闻!

猜你喜欢

转载自blog.csdn.net/weixin_41624982/article/details/86466945