Python并发网络库 Tornado / Gevent 和 异步编程库 Asyncio 及其示例

1.你用过哪些并发网络库?

  Tornado vs Gevent vs Asyncio

Tornado 并发网络库和同时也是一个web微框架

Gevent 绿色线程(greenlet)实现并发,猴子补丁修改内置 socket

Asyncio Python3 内置的并发网络库,基于原生协程

2.Tornado框架

   Tornado 使用于微服务,实现 Restful 接口

底层基于 Linux 多路复用

可以通过协程或者回调实现异步编程

不过生态不完善,相应的异步框架比如ORM不完善

import tornado.ioloop
import tornado.web
from tornado.httpclient import AsyncHTTPClient

class APIHandler(tornado.web.RequestHandler):
    async def get(self):
        url = 'http://httpbin.org/get'
        http_client = AsyncHTTPClient()
        resp = await http_client.fetch(url)   # 异步发送请求    
        print(resp.body)
        return resp.body

def make_app():
    return tornado.web.Application([
        (r"/api", APIHandler)
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(6666)
    tornado.ioloop.IOLoop.current().start()

运行代码后,在终端发送 curl http://localhost:6666/api,获得返回的网页内容如下:

b'{\n "args": {}, \n "headers": {\n "Accept-Encoding": "gzip", \n "Host": "htt

pbin.org"\n }, \n "origin": "223.72.75.28, 223.72.75.28", \n "url": "https://httpbi

n.org/get"\n}\n'

2.Gevent

  高性能的并发网络库

基于轻量级绿色线程( greenlet )实现并发,底层是用C语言实现的

需要注意 monkey patch, gevent 修改了内置的 socket 改为非阻塞

配合 gunicorn 和 gevent 部署作为 wsgi server

#《Gevent 程序员指南》是学习Gevent 的一个比较好的资料

示例:用gevent实现并发爬虫

import gevent.monkey
gevent.monkey.patch_all()   # 修改内置库变成非阻塞 

import gevent
import requests

def fetch(i):
    url = 'http://httpbin.org/get'
    resp = requests.get(url)
    print(len(resp.text), i)  # 返回结果长度,以及序号
    
def asynchronous():
    threads = []
    for i in range(1, 10):    # 添加10个线程
        threads.append(gevent.spawn(fetch, i))
    gevent.joinall(threads)
    
print('Asynchronous:')
asynchronous()

输出结果:

Asynchronous:

252 5

252 1

252 9

252 2

252 7

252 4

252 6

252 3

252 8

    可以看到输出的序号顺序是不一致的,说明使用gevent并发的发的请求,而不是顺序去执行,从而大大提升了请求的效率。

3.Asyncio

  基于协程实现的内置并发网络库,在Py3引入进去。

Python3 引入到内置库,协程+事件循环

生态不够完善,没有大规模生产环境检验

目前应用不够广泛,基于 Aiohttp 可以实现一些小的服务

示例:基于asyncio实现的异步http客户端 aiohttp

# 基于 aiohttp 并发请求
import asyncio
from aiohttp import ClientSession

async def fetch(url, session):
    async with session.get(url) as response:
        return await response.read()
        
async def run(r=10):
    url = "http://httpbin.org/get"
    tasks = []
    
    async with ClientSession() as session:
        for i in range(r):
            task = asyncio.ensure_future(fetch(url, session))
            tasks.append(task)
        responses = await asyncio.gather(*tasks)
        for resp_body in responses:
            print(len(resp_body))
            
loop = asyncio.get_event_loop()  # 获取事件循环
future = asyncio.ensure_future(run())
loop.run_until_complete(future)  # 在事件循环里执行任务

输出结果:

254

254

254

254

254

254

254

254

254

254

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值