前言
《Python asyncio并发编程》旨在介绍如何在Python中利用并行技术提高应用程序的性能、吞吐量和响应能力。本书首先关注并行的核心主题,解释asyncio的单线程并发模型是如何工作的,以及协程和async/await语法的工作原理。然后介绍并发的实际应用,例如并行发出多个 Web 请求或数据库查询、管理线程和进程、构建Web应用程序,以及处理同步问题。
目标读者
本书适用于希望在现有或新的Python应用程序中,更好地理解和使用并发技术的中高级开发人员。本书的立足于在于通过通俗易懂的语言解释复杂的并发技术。你不需要拥有并发经验,当然,如果你拥有这方面的经验,可以更快地理解书中的内容。在本书中,我们将介绍很多知识(从基于Web的API到命令行应用程序),帮助开发人员解决工作中遇到的许多问题。
内容路线图
本书一共14章,前几章介绍基础知识,后几章将介绍更多高级主题。
● 第1章:专注于Python中的基本并发知识。将介绍什么是CPU密集型和I/O密集型工作负载,并介绍asyncio的单线程并发模型的工作原理。
● 第2章:重点介绍asyncio协程的基础知识,以及如何使用async/await语法来构建使用并发的应用程序。
● 第3章:重点介绍非阻塞套接字和选择器如何工作,以及如何使用asyncio构建echo服务器。
● 第4章:重点介绍如何同时发出多个Web请求。通过本章的学习,我们将进一步了解关于并发运行协同程序的核心asyncio API。
● 第5章:重点介绍如何使用连接池同时进行多个数据库查询。还将介绍数据库上下文中的异步上下文管理器和异步生成器。
● 第6章:专注于multiprocessing库,特别是如何将它与asyncio结合,来处理CPU密集型工作。将构建一个map/reduce应用程序来介绍它的工作方法。
● 第7章:专注于多线程,特别是如何将它与asyncio结合来处理阻塞I/O。这对于没有原生asyncio支持但仍然可以从并发中受益的库很有帮助。
● 第8章:着重介绍网络流和协议。将使用网络流和协议来创建一个能同时处理多个用户聊天的服务器和客户端。
● 第9章:主要介绍异步驱动的Web应用程序和ASGI(异步服务器网关接口)。将探索一些ASGI框架,并讨论如何使用它们构建Web API。还将探索 WebSocket。
● 第10章:描述如何使用基于asyncio的Web API来构建微服务架构。
● 第11章:重点讨论单线程并发同步问题,以及如何解决这些问题。将深入研究锁、信号量、事件和条件。
● 第12章:重点关注异步队列。将使用异步队列来构建一个Web应用程序,该应用程序可以即时响应客户端请求,尽管需要在后台执行耗时的工作。
● 第13章:专注于创建和管理子进程,展示如何读取和写入数据。
● 第14章:专注于高级主题,例如强制事件循环迭代、上下文变量和创建自己的事件循环。这些信息对于asyncio API设计者和那些对asyncio事件循环的内部运作流程感兴趣的人十分有帮助。
对于读者来说,你应该仔细阅读前四章的内容,从而全面了解asyncio的工作原理、如何构建第一个真正的应用程序,以及如何使用核心asyncio API来并行运行协同程序(将在第4章中介绍)。此后,你可以根据自己的兴趣来阅读本书。
关于代码
本书包含许多代码示例,包括编号的代码清单。一些代码清单在同一章后面的清单中被重用,有些则在多个章节中被重用。对于跨多个章节重用的代码,将假定你已经创建了一个名为util的模块(你将在第2章中创建它)。对于每个单独的代码清单,假设你为该章创建了一个名为chapter_{chapter_number}的模块,然后将代码放入格式为listing_{chapter_number}_{listing_number}的Python文件中。例如,第2章中清单2-2的代码将位于一个名为chapter_2的模块中,该模块保存在名为listing_2_2.py的文件中。
书中多处提到性能数字,例如程序完成的时间或每秒完成的Web请求。本书中的代码示例运行在配备2.4GHz 8 核 Intel Core i9处理器和 32GB 2667 MHz DDR4 RAM 的2019 MacBook Pro上,并进行了基准测试,使用千兆无线互联网连接。根据你运行的机器,这些数字会有所不同,加速或改进的因素也会有所不同。
本书中使用的代码可通过扫描封底二维码下载。
商品简介
作者简介
Matthew Fowler拥有近20年的软件工程经验,曾任软件架构师、工程总监等多个职位。他起初为科学应用程序编写软件,然后转向全栈Web开发和分布式系统,最终领导多个开发人员和管理人员团队为拥有数千万用户的电子商务网站编写应用程序及构建系统。他与妻子Kathy住在马萨诸塞州的列克星敦。
目录
第1章asyncio简介1
1.1什么是asyncio2
1.2什么是I/O密集型和CPU密集型3
1.3了解并发、并行和多任务处理4
1.3.1并发4
1.3.2并行5
1.3.3并行与并发的区别6
1.3.4什么是多任务6
1.3.5协同多任务处理的优势7
1.4了解进程、线程、多线程和多处理7
1.4.1进程7
1.4.2线程8
1.5理解全局解释器锁11
1.5.1GIL会释放吗15
1.5.2asyncio和GIL17
1.6单线程并发17
1.7事件循环的工作原理20
1.8本章小结22
第2章asyncio基础23
2.1关于协程23
2.1.1使用async关键字创建协程24
2.1.2使用await关键字暂停执行26
2.2使用sleep引入长时间运行的协程27
2.3通过任务实现并行30
2.3.1创建任务30
2.3.2同时运行多个任务31
2.4取消任务和设置超时34
2.4.1取消任务34
2.4.2设置超时并使用wait_for执行取消36
2.5任务、协程、future和awaitable38
2.5.1关于future38
2.5.2future、任务和协程之间的关系40
2.6使用装饰器测量协程执行时间41
2.7协程和任务的陷阱43
2.7.1运行CPU密集型代码44
2.7.2运行阻塞API46
2.8手动创建和访问事件循环47
2.8.1手动创建事件循环47
2.8.2访问事件循环48
2.9使用调试模式49
2.9.1使用asyncio.run49
2.9.2使用命令行参数49
2.9.3使用环境变量50
2.10本章小结51
第3章第一个asyncio应用程序53
3.1使用阻塞套接字54
3.2使用telnet连接到服务器56
3.2.1从套接字读取和写入数据57
3.2.2允许多个连接和阻塞的危险性59
3.3使用非阻塞套接字61
3.4使用选择器模块构建套接字事件循环65
3.5使用asyncio事件循环的
回显服务器68
3.5.1套接字的事件循环协程69
3.5.2设计一个异步回显服务器69
3.5.3解决任务中的错误72
3.6正常关闭74
3.6.1监听信号74
3.6.2等待挂起的任务完成76
3.7本章小结79
第4章并发网络请求81
4.1aiohttp82
4.2异步上下文管理器82
4.2.1使用aiohttp发出Web请求85
4.2.2使用aiohttp设置超时87
4.3并发运行任务及重新访问88
4.4通过gather执行并发请求91
4.5在请求完成时立即处理95
4.6使用wait进行细粒度控制99
4.6.1等待所有任务完成99
4.6.2观察异常102
4.6.3当任务完成时处理结果104
4.6.4处理超时107
4.6.5为什么要将所有内容都包装在一个任务中109
4.7本章小结110
第5章非阻塞数据库驱动程序111
5.1关于asyncpg111
5.2连接Postgres数据库112
5.3定义数据库模式113
5.4使用asyncpg执行查询116
5.5通过连接池实现并发查询119
5.5.1将随机sku插入products数据库119
5.5.2创建连接池从而同时运行查询123
5.6使用asyncpg管理事务128
5.6.1嵌套事务130
5.6.2手动管理事务132
5.7异步生成器和流式结果集133
5.7.1异步生成器介绍134
5.7.2使用带有流游标的异步生成器135
5.8本章小结139
第6章处理CPU密集型工作141
6.1介绍multiprocessing库142
6.2使用进程池144
6.3进程池执行器与asyncio146
6.3.1进程池执行器146
6.3.2带有异步事件循环的进程池执行器148
6.4使用asyncio解决MapReduce的问题149
6.4.1简单的MapReduce示例151
6.4.2GoogleBooksNgram数据集153
6.4.3使用asyncio进行映射和归约154
6.5共享数据和锁159
6.5.1共享数据和竞争条件160
6.5.2使用锁进行同步163
6.5.3与进程池共享数据166
6.6多进程,多事件循环170
6.7本章小结173
第7章通过线程处理阻塞任务175
7.1threading模块176
7.2通过asyncio使用线程180
7.2.1request库180
7.2.2线程池执行器181
7.2.3使用asyncio的线程池执行器183
7.2.4默认执行器184
7.3锁、共享数据和死锁186
7.3.1可重入锁188
7.3.2死锁190
7.4单线程中的事件循环192
7.4.1Tkinter193
7.4.2使用asyncio和线程构建响应式UI195
7.5使用线程执行CPU密集型工作203
7.5.1多线程与hashlib203
7.5.2多线程与NumPy206
7.6本章小结208
第8章流211
8.1流212
8.2传输和协议212
8.3流读取与流写入216
8.4非阻塞命令行输入219
8.5创建服务器230
8.6创建聊天服务器和客户端232
8.7本章小结239
第9章Web应用程序241
9.1使用aiohttp创建RESTAPI242
9.1.1什么是REST242
9.1.2aiohttp服务器基础知识243
9.1.3连接到数据库并返回结果244
9.1.4比较aiohttp和Flask251
9.2异步服务器网关接口253
9.3ASGI与Starlette255
9.3.1使用Starlette的REST端点255
9.3.2WebSocket与Starlette257
9.4Django异步视图261
9.4.1在异步视图中运行阻塞工作267
9.4.2在同步视图中使用异步代码268
9.5本章小结269
第10章微服务271
10.1什么是微服务272
10.1.1代码的复杂性272
10.1.2可扩展性272
10.1.3团队和堆栈独立性273
10.1.4asyncio如何提供帮助273
10.2backend-for-frontend模式273
10.3实施产品列表API275
10.3.1“用户收藏”服务275
10.3.2实现基础服务276
10.3.3实现backend-for-frontend服务281
10.3.4重试失败的请求287
10.3.5断路器模式290
10.4本章小结296
第11章同步297
11.1了解单线程并发错误298
11.2锁302
11.3使用信号量并发性306
11.4使用事件来通知任务312
11.5条件317
11.6本章小结322
第12章异步队列323
12.1异步队列基本知识324
12.1.1Web应用程序中的队列331
12.1.2网络爬虫队列334
12.2优先级队列337
12.3LIFO队列345
12.4本章小结347
第13章管理子进程349
13.1创建子进程349
13.1.1控制标准输出352
13.1.2同时运行子进程355
13.2与子进程进行通信359
13.3本章小结363
第14章高级asyncio365
14.1带有协程和函数的API366
14.2上下文变量368
14.3强制事件循环迭代370
14.4使用不同的事件循环实现371
14.5创建自定义事件循环373
14.5.1协程和生成器373
14.5.2不建议使用基于生成器的协程374
14.5.3自定义可等待对象376
14.5.4使用带有future的套接字379
14.5.5任务的实现381
14.5.6实现事件循环383
14.5.7使用自定义事件循环实现服务器386
14.6本章小结388
内容摘要
标准Python程序很容易过载,从而出现慢如龟爬的情况。asyncio库正是为了解决这些问题而构建的,它简化了任务的划分和调度。asyncio可无缝地同时处理多个操作,使应用程序疾如闪电,且具有扩展性。本书在大量示例的引导下,介绍异步、并行和并发编程。将难理解的并发内容分解为简明易懂的流程图,使读者可轻松了解任务的运行方式。在本书中,读者将学习如何使用asyncio来突破Python的,从而加快Web服务器和微服务的运行速度。读者甚至可将asyncio与传统的多处理技术结合起来,以大幅提升性能。
主编推荐
在本书中,通过14章的内容,由浅入深地介绍如何通过asyncio实现并发编程,并使用 一个贯穿全书的示例,介绍如何使用asyncio 在服务器与客户端之间进行并发通信。看着这个示例由简单变得复杂,在掌握相关知识的同时,也给自己带来了不小的成就感。作为Python和数据科学的教学人员,我建议你在阅读本书时,认真学习书中的示例,并在自己的计算机上运行本书附带的程序,这将让你更好地理解本书所介绍的内容。别担心,本书使用的示例对计算机的要求并不高;我在完成相关练习时,使用的是2015年在拉斯维加斯的Best buy购买的MacBook Pro,配置i5 CPU、8GB
内存及128GB SSD,使用这样的机器运行本书的示例代码毫无压力。
以下为对购买帮助不大的评价