首页 > 编程 > Python > 正文

Python使用asyncio包处理并发详解

2020-02-16 10:13:33
字体:
来源:转载
供稿:网友

阻塞型I/O和GIL

CPython 解释器本身就不是线程安全的,因此有全局解释器锁(GIL),一次只允许使用一个线程执行 Python 字节码。因此,一个 Python 进程通常不能同时使用多个 CPU 核心。

然而,标准库中所有执行阻塞型 I/O 操作的函数,在等待操作系统返回结果时都会释放GIL。这意味着在 Python 语言这个层次上可以使用多线程,而 I/O 密集型 Python 程序能从中受益:一个 Python 线程等待网络响应时,阻塞型 I/O 函数会释放 GIL,再运行一个线程。

asyncio

这个包使用事件循环驱动的协程实现并发。 asyncio 大量使用 yield from 表达式,因此与Python 旧版不兼容。

asyncio 包使用的“协程”是较严格的定义。适合asyncio API 的协程在定义体中必须使用 yield from,而不能使用 yield。此外,适合 asyncio 的协程要由调用方驱动,并由调用方通过 yield from 调用;

示例1

import threadingimport asyncio@asyncio.coroutinedef hello():  print('Start Hello', threading.currentThread())  yield from asyncio.sleep(5)  print('End Hello', threading.currentThread())@asyncio.coroutinedef world():  print('Start World', threading.currentThread())  yield from asyncio.sleep(3)  print('End World', threading.currentThread())# 获取EventLoop:loop = asyncio.get_event_loop()tasks = [hello(), world()]# 执行coroutineloop.run_until_complete(asyncio.wait(tasks))loop.close()

@asyncio.coroutine把生成器函数标记为协程类型。
asyncio.sleep(3) 创建一个3秒后完成的协程。
loop.run_until_complete(future),运行直到future完成;如果参数是 coroutine object,则需要使用 ensure_future()函数包装。
loop.close() 关闭事件循环

示例2

import asyncio@asyncio.coroutinedef worker(text):  """  协程运行的函数  :param text:  :return:  """  i = 0  while True:    print(text, i)    try:      yield from asyncio.sleep(.1)    except asyncio.CancelledError:      break    i += 1@asyncio.coroutinedef client(text, io_used):  worker_fu = asyncio.ensure_future(worker(text))  # 假装等待I/O一段时间  yield from asyncio.sleep(io_used)  # 结束运行协程  worker_fu.cancel()  return 'done'loop = asyncio.get_event_loop()tasks = [client('xiaozhe', 3), client('zzzz', 5)]result = loop.run_until_complete(asyncio.wait(tasks))loop.close()print('Answer:', result)

解释:

1. asyncio.ensure_future(coro_or_future, *, loop=None):计划安排一个 coroutine object的执行,返回一个 asyncio.Task object。
2. worker_fu.cancel(): 取消一个协程的执行,抛出CancelledError异常。
3. asyncio.wait():协程的参数是一个由期物或协程构成的可迭代对象; wait 会分别把各个协程包装进一个 Task 对象。

asyncio.Task 对象与threading.Thread对象的比较

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表