线程和asyncio的比较

本文借助动态转圈圈的例子展示

import sys
import itertools
import time
import threading


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))
        if not signal.go:
            break
    write('x08' * len(status))


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


def supervisor():
    signal = Signal()
    spinner = threading.Thread(target=spin, args=('hahaha', signal))
    print('spin obj:', spinner)
    spinner.start()
    result = slow_func()
    signal.go = False  # 结束一个线程
    spinner.join()
    return result


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


if __name__ == '__main__':
    main()
import sys
import asyncio
import itertools


@asyncio.coroutine
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:
            yield from asyncio.sleep(.1)
        except asyncio.CancelledError as e:
            break


@asyncio.coroutine
def slow_func():
    yield from asyncio.sleep(3)
    return 42

@asyncio.coroutine
def supervisor():
    spinner = asyncio.Task(spin('hahaha'))
    print('spin obj:', spinner)
    result = yield from slow_func()
    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方法对比:

1.asyncio.Task对象差不多与threading.Thread对象等效。

2.Tas对象用于驱动协程,Thread对象用于调用可调用的对象

3.Task对象不用自己手动创建,而是通过把携程穿过asyncio.async(...)函数或loop.create_task(...)方法获取

4.获取的Task对象已经排定了运行时间(例如,有asyncio.async函数排定);Thread实例必须调用start方法,明确告知让他运行。

5.线程版supervisor函数中,slow_func是普通函数,直接有线程调用。

   异步版supervisor函数中,slow_func是协程,有yield from驱动。

6.没有API能从外部终止线程,因为线程随时可能被中断,导致系统处于无效状态。如果想终止任务,可以使用Task.cancel()实例方法,在协程内部抛出CanceledError异常。协程可以在暂停的yield处捕获这个异常,处理终止请求。

7.supervisor协程必须在main函数中由loop.run_until_complete方法执行。

原文地址:https://www.cnblogs.com/liuer-mihou/p/11940224.html