流畅的python,Fluent Python 第十八章笔记 (使用asyncio包处理并发)

书中的代码用的应该是Python3.3的,从Python3.5开始协程用async 与await 代替了@asyncio.coroutine与yield.from

话说asyncio与aiohttp配合使用,从书中的教程来看真的非常强大,以后的并发io处理,协程才是王道了。

18.1线程与协程对比

import threading
import itertools
import time
import sys


class Signal:
    go = True


def spin(msg, signal):
    write, flush = sys.stdout.write, sys.stdout.flush
    for char in itertools.cycle('|/-\\'):
        status = char + ' ' + msg
        write(status)
        flush()
        write('\x08' * len(status))
        time.sleep(.1)
        if not signal.go:
            break
    write(' ' * len(status) + '\x08' * len(status))


def slow_function():
    time.sleep(3)
    return 42


def supervisor():
    singal = Signal()
    spinner = threading.Thread(target=spin, args=('thinking!', singal))
    print('spinner object:', spinner)
    # spinner线程开始
    spinner.start()
    # 主线程休眠
    result = slow_function()
    # 给spinner线程发送关闭信号
    singal.go = False
    spinner.join()
    return result


def main():
    result = supervisor()
    print('Answer', result)


if __name__ == '__main__':
    main()

 这个一个多线程的显示脚本,一共两个线程,主线程负责显示最后的输出,开辟的子线程负责显示转圈圈。

import asyncio
import itertools
import sys



async def spin(msg):
    write, flush = sys.stdout.write, sys.stdout.flush
    for char in itertools.cycle('|/-\\'):
        status = char + ' ' + msg
        write(status)
        flush()
        # 继续回到初始位置
        write('\x08' * len(status))
        try:
            await asyncio.sleep(.1)
        # 捕获错误
        except asyncio.CancelledError:
            break
    write(' ' * len(status) + '\x08' * len(status))



async def slow_function():
    await asyncio.sleep(3)
    return 42



async def supervisor():
    # 把协程包装成为一个task任务
    spinner = asyncio.ensure_future(spin('thinking!'))
    # 已经是一个任务返回的还是一个任务
    spinner = asyncio.ensure_future(spinner)
    print('spinner object:', spinner)
    # 激活等待slow_function任务,由于slow_function里面有sleep,会把控制权,到时候会把控制权转给spinnner
    slow_function1 = asyncio.ensure_future(slow_function())
    result = await slow_function1
    # 得到result,取消spinner任务
    # await asyncio.sleep(5)
    spinner.cancel()
    return result

def main():
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(supervisor())
    loop.close()
    print('Answer', result)

if __name__ == '__main__':
    main()

 这是一个协程版本的,最后的协程supervisor()里面一共有两个任务,通过await asyncio.sleep()切换协程的工作。

asyncio.ensure_future(...)接收的是一个协程,排定它的运作时间,排定它的运行时间,然后返回个asyncio.Task实例,也就是asyncio.Future的实例,因为Task
是Future的子类,用于包装协程。

task或者future都有.done(), .add_done_callback(....)和.result()等方法,

只不过这些方法一般用的比较少,只要result=await myfuture(),其中await后面需要回调的参数就是,result就是task的result。

 

猜你喜欢

转载自www.cnblogs.com/sidianok/p/12231548.html
今日推荐