asyncio 包处理并发并发是指一次处理多件事。
并行是指一次做多件事。
二者不同,但是有联系。
一个关于结构,一个关于执行。
并发用于制定方案,用来解决可能(但未必)并行的问题。1——Rob Pike
Go 语言的创造者之一
1摘自“Concurrency Is Not Parallelism (It's Better)”(http://concur.rspace.googlecode.com/hg/talk/concur.html#slide-5)演讲的第 5 张幻灯片。
Imre Simon 教授 2 说过,科学界有两个重要过错:使用不同的词表示相同的事物,以及使用同一个词表示不同的事物。如果你研究过并发编程或并行编程,会发现“并发”和“并行”有不同的定义。我将采用上述引文中 Rob Pike 的非正式定义。
2Imre Simon(1943—2009)是巴西的计算机科学先驱,对自动机理论(Automata Theory)有杰出的贡献,开创了热带数学(Tropical Mathematics)这一领域。他还是自由软件和自由文化的拥护者。我有幸曾与他一起学习、工作和相处。
真正的并行需要多个核心。现代的笔记本电脑有4个 CPU 核心,但是通常不经意间就有超过 100 个进程同时运行。因此,实际上大多数过程都是并发处理的,而不是并行处理。计算机始终运行着 100 多个进程,确保每个进程都有机会取得进展,不过 CPU 本身同时做的事情不能超过四件。十年前使用的设备也能并发处理 100 个进程,不过都在同一个核心里。鉴于此,Rob Pike 才把那次演讲取名为“Concurrency Is Not Parallelism (It's Better)”[“并发不是并行(并发更好)”]。
本章介绍 asyncio 包,这个包使用事件循环驱动的协程实现并发。这是 Python 中最大也是最具雄心壮志的库之一。Guido van Rossum 在 Python 仓库之外开发 asyncio 包,把这个项目的代号命名为“Tulip”(郁金香)。因此,在网上搜索这方面的资料时,会经常看到这种花的名称。例如,这个项目的主要讨论组仍叫 python-tulip(https://groups.google.com/forum/#!forum/python-tulip)。
Python 3.4 把 Tulip 添加到标准库中时,把它重命名为 asyncio。这个包也兼容 Python 3.3,在 PyPI 中可以通过新的官方名称找到(https://pypi.python.org/pypi/asyncio)。asyncio 大量使用 yield from 表达式,因此与 Python 旧版不兼容。
Trollius 项目(也以花名命名,http://trollius.readthedocs.org/)移植了
asyncio,把yield from替换成yield和精巧的回调(From和Return),以便支持 Python 2.6 及以上版本。yield from ...表达式变成了yield From(...);如果协程需要返回结果,那么要把return result替换成raise Return(result)。Trollius 由 Victor Stinner 主导,他也是asyncio包的核心开发者。Victor 人很好,在本书付梓之前同意审核本章。
本章讨论以下话题:
对比一个简单的多线程程序和对应的 asyncio 版,说明多线程和异步任务之间的关系
asyncio.Future 类与 concurrent.futures.Future 类之间的区别
第 17 章中下载国旗那些示例的异步版
摒弃线程或进程,如何使用异步编程管理网络应用中的高并发
在异步编程中,与回调相比,协程显著提升性能的方式
如何把阻塞的操作交给线程池处理,从而避免阻塞事件循环
使用 asyncio 编写服务器,重新审视 Web 应用对高并发的处理方式
为什么 asyncio 已经准备好对 Python 生态系统产生重大影响
首先,本章通过简单的示例来对比 threading 模块和 asyncio 包。