Python异步IO

Posted gzhjj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python异步IO相关的知识,希望对你有一定的参考价值。

在IO操作的过程中,当前线程被挂起,而其他需要CPU执行的代码就无法被当前线程执行了。
我们可以使用多线程或者多进程来并发执行代码,为多个用户服务。
但是,一旦线程数量过多,CPU的时间就花在线程切换上了,真正运行代码的时间就少了,结果导致性能严重下降。
异步IO:当代码需要执行一个耗时的IO操作时,它只发出IO指令,并不等待IO结果,然后就去执行其他代码了。一段时间后,当IO返回结果时,再通知CPU进行处理。
对于大多数IO密集型的应用程序,使用异步IO将大大提升系统的多任务处理能力。

1. 异步IO

1.1 协程

协程,又称微线程,纤程。英文名Coroutine
子程序(函数)调用是通过栈实现的,一个线程就是执行一个子程序。
协程的执行过程中,在子程序内部可中断,然后转而去执行别的子程序,在适当的时候再回来接着执行。
Python对协程的支持是通过生成器实现的。
在生成器中,我们不但可以通过for循环来迭代,还可以不断调用next()函数获取由yield语句返回的下一个值。但是Pythonyield不但可以返回一个值,它还可以接收调用者发出的参数。

def consumer():
    r = \'\'
    while True:
        n = yield r
        if not n:
            return
        print(\'[CONSUMER] Consuming %s...\' % n)
        r = \'200 OK\'

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print(\'[PRODUCER] Producing %s...\' % n)
        r = c.send(n)
        print(\'[PRODUCER] Consumer return: %s\' % r)
    c.close()

c = consumer()
produce(c)

[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

1.2 asyncio

asyncio的编程模型是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。

import asyncio

@asyncio.coroutine
def hello():
    print("Hello world!")
    # 异步调用asyncio.sleep(1):
    r = yield from asyncio.sleep(1)
    print("Hello again!")

# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()

@asyncio.coroutine把一个生成器标记为协程类型,然后,我们就把这个协程扔到EventLoop中执行。

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())

loop = asyncio.get_event_loop()
tasks = [hello(), hello()] # 封装两个协程
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

# Hello world! (<_MainThread(MainThread, started 9700)>)
# Hello world! (<_MainThread(MainThread, started 9700)>)
# Hello again! (<_MainThread(MainThread, started 9700)>)
# Hello again! (<_MainThread(MainThread, started 9700)>)

1.3 async/await

import asyncio

async def hello():
    print("Hello world!")
    r = await asyncio.sleep(1)
    print("Hello again!")
	
	
# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()

1.4 aiohttp

import asyncio

from aiohttp import web

async def index(request):
    await asyncio.sleep(0.5)
    return web.Response(body=\'<h1>Index</h1>\'.encode(\'utf-8\'), content_type=\'text/html\')

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\'), content_type=\'text/html\')

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()

参考资料:

以上是关于Python异步IO的主要内容,如果未能解决你的问题,请参考以下文章

python随用随学20200220-异步IO

Python 异步 io 流

Python基础入门自学——22--异步IO

python 多进程和多线程3 —— asyncio - 异步IO

python 多进程和多线程3 —— asyncio - 异步IO

Python学习---IO的异步[自定义异步IO]