zoukankan      html  css  js  c++  java
  • 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()
    
    

    参考资料:

  • 相关阅读:
    java中如何制作可双击执行的程序--jar打包工具的使用
    GUI菜单——菜单条、菜单、子条目之间关系
    设计模式——单例模式(饿汉式、懒汉式)
    深入理解利用new创建对象的执行过程以Person p=new Person("张三",20);为例
    构造代码块、构造函数、this执行顺序
    OpenGL 动画的制作
    UE4制作插件的插件神器pluginCreator
    3dmax中cs骨骼教程
    如何解决 应用程序无法启动 因为应用程序的并行配置不正确 问题
    如何自学游戏引擎的开发
  • 原文地址:https://www.cnblogs.com/gzhjj/p/10674162.html
Copyright © 2011-2022 走看看