Python中篇 :2. asyncio和多线程结合实战

简介: Python中篇 :2. asyncio和多线程结合实战

1. 前言



看到这个题目大家觉得很慌,我都协程并发处理数据了,为什么还需要线程?孰轻孰重我们当然想的清楚,但是这里的门道就是一句话:我不管你异步编程多么NB,我就是想一边用异步,一边调用同步阻塞的代码,我不管我就这样用,你就说能不能办到?这可把我难倒了,上节课不是说了异步编程核心原则:要异步,所有的都要异步,感觉与其背道而驰啊。经过一番研究发现:草率了,异步中可以调用同步的代码,但是吃相比较难看而已罢了


2. 异步+同步



import time
import asyncio
from concurrent.futures.thread import ThreadPoolExecutor
# 同步阻塞代码
def run():
    time.sleep(2)
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    start = time.time()
    executor = ThreadPoolExecutor() # 初始化线程池
    tasks = []
    for i in range(20):
        task = loop.run_in_executor(executor, run)
        tasks.append(task)
    loop.run_until_complete(asyncio.wait(tasks)) # 异步调用
    print("total time: ", time.time()-start)


执行时间:


total time:  4.015759229660034

20个同步阻塞任务在经过异步+同步调用之后时间增加了,但这是相比较于协程得出的结论(我们下面会分析)。我们可以看到程序通过ThreadPoolExecutor创建线程池,最后通过loop的run_in_executor把线程的future包装成协程的future,最后被loop的run_until_complete调度。


线程转换为协程 核心


为什么线程future可以转换成协程呢?

核心就是loop.run_in_executor方法,源码大家下去可以自己看,我只提取重点:return futures.wrap_future(executor.submit(func, *args), loop=self),看到了吗,线程执行的结果即executor.submit的返回值设置到concurrent.futures.Future对象里面(记为future1),而协程通过loop.create_future创建自己的future(记为future2),最后通过_chain_future将二者的future关联起来,即_chain_future(future1, future2),最后把future2返回,供loop调度。

分析到最后我忍不住感叹:吉多·范罗苏姆,你是一个天才选手。


3. all in 异步



import asyncio
import time
async def run1():
    await asyncio.sleep(2)
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    start = time.time()
    tasks = []
    for i in range(20):
        tasks.append(run1())
    loop.run_until_complete(asyncio.wait(tasks))
    print("total time: ", time.time()-start)


运行结果如下:


total time:  2.0061399936676025

看到了吗?同样的代码逻辑,只要你把同步改成异步,那么效率会大大提升,即使有20个任务,每个任务sleep 2s,协程照样照单全收,几乎就是2s把所有任务执行完成,这效率无敌啊。


4. 小结



相信大家看到这里还有一点疑惑,到底哪种情况全是异步,那种情况同步+异步呢?来吧,开始你的表演:新项目,全是异步; 旧项目,看注释,说别动就别动,你动,就是bug,不动,万无一失,该如何破?教你一招:大胆破局

相关文章
|
13天前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
14天前
|
数据采集 机器学习/深度学习 人工智能
Python编程入门:从基础到实战
【10月更文挑战第36天】本文将带你走进Python的世界,从基础语法出发,逐步深入到实际项目应用。我们将一起探索Python的简洁与强大,通过实例学习如何运用Python解决问题。无论你是编程新手还是希望扩展技能的老手,这篇文章都将为你提供有价值的指导和灵感。让我们一起开启Python编程之旅,用代码书写想法,创造可能。
|
8天前
|
数据采集 Java Python
爬取小说资源的Python实践:从单线程到多线程的效率飞跃
本文介绍了一种使用Python从笔趣阁网站爬取小说内容的方法,并通过引入多线程技术大幅提高了下载效率。文章首先概述了环境准备,包括所需安装的库,然后详细描述了爬虫程序的设计与实现过程,包括发送HTTP请求、解析HTML文档、提取章节链接及多线程下载等步骤。最后,强调了性能优化的重要性,并提醒读者遵守相关法律法规。
40 0
|
11天前
|
数据采集 存储 数据处理
探索Python中的异步编程:从基础到实战
【10月更文挑战第39天】在编程世界中,时间就是效率的代名词。Python的异步编程特性,如同给程序穿上了一双翅膀,让它们在执行任务时飞得更高、更快。本文将带你领略Python异步编程的魅力,从理解其背后的原理到掌握实际应用的技巧,我们不仅会讨论理论基础,还会通过实际代码示例,展示如何利用这些知识来提升你的程序性能。准备好让你的Python代码“起飞”了吗?让我们开始这场异步编程的旅程!
26 0
|
15天前
|
并行计算 数据挖掘 大数据
Python数据分析实战:利用Pandas处理大数据集
Python数据分析实战:利用Pandas处理大数据集
|
1月前
|
搜索推荐 程序员 调度
精通Python异步编程:利用Asyncio与Aiohttp构建高效网络应用
【10月更文挑战第5天】随着互联网技术的快速发展,用户对于网络应用的响应速度和服务质量提出了越来越高的要求。为了构建能够处理高并发请求、提供快速响应时间的应用程序,开发者们需要掌握高效的编程技术和框架。在Python语言中,`asyncio` 和 `aiohttp` 是两个非常强大的库,它们可以帮助我们编写出既简洁又高效的异步网络应用。
131 1
|
16天前
|
Python
Python中的异步编程:使用asyncio和aiohttp实现高效网络请求
【10月更文挑战第34天】在Python的世界里,异步编程是提高效率的利器。本文将带你了解如何使用asyncio和aiohttp库来编写高效的网络请求代码。我们将通过一个简单的示例来展示如何利用这些工具来并发地处理多个网络请求,从而提高程序的整体性能。准备好让你的Python代码飞起来吧!
39 2
|
20天前
|
调度 开发者 Python
Python中的异步编程:理解asyncio库
在Python的世界里,异步编程是一种高效处理I/O密集型任务的方法。本文将深入探讨Python的asyncio库,它是实现异步编程的核心。我们将从asyncio的基本概念出发,逐步解析事件循环、协程、任务和期货的概念,并通过实例展示如何使用asyncio来编写异步代码。不同于传统的同步编程,异步编程能够让程序在等待I/O操作完成时释放资源去处理其他任务,从而提高程序的整体效率和响应速度。
|
3天前
|
API 开发者 Python
探索Python中的异步编程:Asyncio与Tornado的对决
在这个快节奏的世界里,Python开发者面临着一个挑战:如何让代码跑得更快?本文将带你走进Python异步编程的两大阵营——Asyncio和Tornado,探讨它们如何帮助我们提升性能,以及在实际应用中如何选择。我们将通过一场虚拟的“对决”,比较这两个框架的性能和易用性,让你在异步编程的战场上做出明智的选择。
|
29天前
|
关系型数据库 MySQL 数据处理
探索Python中的异步编程:从asyncio到异步数据库操作
在这个快节奏的技术世界里,效率和性能是关键。本文将带你深入Python的异步编程世界,从基础的asyncio库开始,逐步探索到异步数据库操作的高级应用。我们将一起揭开异步编程的神秘面纱,探索它如何帮助我们提升应用程序的性能和响应速度。
下一篇
无影云桌面