Skip to content

使用asyncio包处理并发

此笔记记录于《流畅的python》,大部分为其中的摘要,少部分为笔者自己的理解;笔记为jupyter转的markdown,原始版jupyter笔记在这个仓库

线程与协程对比

通过线程以动画形式显示文本式旋转指针:

python
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():
    # 假装等待I/O一段时间
    time.sleep(3)
    return 42


def supervisor():
    signal = Signal()
    spinner = threading.Thread(target=spin,
                               args=('thinking!', signal))
    print('spinner object:', spinner)
    spinner.start()
    result = slow_function()
    signal.go = False
    spinner.join()
    return result


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


if __name__ == '__main__':
    main()
spinner object: <Thread(Thread-5 (spin), initial)>
| thinking/ thinking- thinking\ thinking| thinking/ thinking- thinking\ thinking| thinking/ thinking- thinking\ thinking| thinking/ thinking- thinking\ thinking| thinking/ thinking- thinking\ thinking| thinking/ thinking- thinking\ thinking| thinking/ thinking- thinking\ thinking          Answer: 42

通过协程以动画形式显示文本式旋转指针(3.7语法已经更新)

python
import asyncio
import itertools
import sys


async def spin(msg):  # 使用async定义协程
    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)  # 使用await
        except asyncio.CancelledError:
            break
    write(' ' * len(status) + '\x08' * len(status))


async def slow_function():  # 使用async定义协程
    # 假装等待I/O一段时间
    await asyncio.sleep(3)  # 使用await
    return 42


async def supervisor():  # 使用async定义协程
    spinner = asyncio.create_task(spin('thinking!'))  # 使用asyncio.create_task()
    print('spinner object:', spinner)
    result = await slow_function()  # 使用await
    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()

略略略...