python之异步IO
协程的用武之地
-
并发量较大的系统和容易在IO方面出现瓶颈(磁盘IO,网络IO),采用多线程、多进程可以解决这个问题,当然线程、进程的切换时很消耗资源的。最好的解决方案是使用单线程方式解决并发IO问题--这就是协程发挥作用之处。
-
协程其实就是单线程在调度,是无法利用多核CPU,所以对于计算密集型的任务还是需要考虑多进程+协程的方式。
参考:
http://blog.csdn.net/qq910894904/article/details/41699541
http://www.cnblogs.com/xone/p/6198500.html
异步IO库之asyncio
-
asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。
-
asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
import asyncio import threading @asyncio.coroutine def hello(index): print('hello world! index=%s,thread=%s' % (index,threading.currentThread())) yield from asyncio.sleep(1) print('hello again! index=%s,thread=%s' % (index,threading.currentThread())) loop=asyncio.get_event_loop() tasks=[hello(i) for i in range(10000)] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
import asyncio @asyncio.coroutine def wget(url): print('wget %s...' % (url)) connection = asyncio.open_connection(url,80) reader,writer=yield from connection header = 'GET / HTTP/1.0\r\nHOST: %s\r\n\r\n' % url writer.write(header.encode('utf-8')) yield from writer.drain() while True: line = yield from reader.readline() if line == b'\r\n': break print('%s header > %s' % (url,line.decode('utf-8').rstrip())) writer.close() loop = asyncio.get_event_loop() tasks=[wget(url) for url in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
async和await
- 为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。(其实Net中也有这个东东)
参考:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00144661533005329786387b5684be385062a121e834ac7000
aiohttp
- aiohttp则是基于asyncio实现的HTTP框架
- 于HTTP连接就是IO操作,因此可以用单线程+coroutine实现多用户的高并发支持
import asyncio from aiohttp import web async def index(request): await asyncio.sleep(0.5) return web.Response(body=b'<h1>Index</h1>') async def hello(request): await asyncio.sleep(0.5) text = '<h1>hello, %s!</h1>' % request.match_info['name'] return web.Response(body=text.encode('utf-8')) async def init(loop): app = web.Application(loop=loop) app.router.add_route('GET', '/', index) app.router.add_route('GET', '/hello/{name}', hello) srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000) print('Server started at http://127.0.0.1:8000...') return srv loop = asyncio.get_event_loop() loop.run_until_complete(init(loop)) loop.run_forever()
报异常了:
from aiohttp import web
ImportError: cannot import name 'web'
以上问题不知道是不是因为版本问题?待解决...........