python教程:使用 async 和 await 协程进行并发编程
python 一直在进行并发编程的优化, 比较熟知的是使用 thread 模块多线程和 multiprocessing 多进程,后来慢慢引入基于 yield 关键字的协程。 而近几个版本,python 对于协程的写法进行了大幅的优化,很多之前的协程写法不被官方推荐了。如果你之前了解过 python 协程,你应该看看最新的用法。
并发、并行、同步和异步
并发指的是 一个 CPU 同时处理多个程序,但是在同一时间点只会处理其中一个。并发的核心是:程序切换。
但是因为程序切换的速度非常快,1 秒钟内可以完全很多次程序切换,肉眼无法感知。
并行指的是多个 CPU 同时处理多个程序,同一时间点可以处理多个。
同步:执行 IO 操作时,必须等待执行完成才得到返回结果。
异步:执行 IO 操作时,不必等待执行就能得到返回结果。
协程,线程和进程的区别
多进程通常利用的是多核 CPU 的优势,同时执行多个计算任务。每个进程有自己独立的内存管理,所以不同进程之间要进行数据通信比较麻烦。
多线程是在一个 cpu 上创建多个子任务,当某一个子任务休息的时候其他任务接着执行。多线程的控制是由 python 自己控制的。 子线程之间的内存是共享的,并不需要额外的数据通信机制。但是线程存在数据同步问题,所以要有锁机制。
协程的实现是在一个线程内实现的,相当于流水线作业。由于线程切换的消耗比较大,所以对于并发编程,可以优先使用协程。
。。。
这是对比图:
协程的基础使用
这是 python 3.7 里面的基础协程用法,现在这种用法已经基本稳定,不太建议使用之前的语法了。
import asyncio
import time
async def visit_url(url, response_time):
"""访问 url"""
await asyncio.sleep(response_time)
return f"访问{url}, 已得到返回结果"
start_time = time.perf_counter()
task = visit_url('http://wangzhen.com', 2)
asyncio.run(task)
print(f"消耗时间:{time.perf_counter() - start_time}")
- 1, 在普通的函数前面加 async 关键字;
- 2,await 表示在这个地方等待子函数执行完成,再往下执行。(在并发操作中,把程序控制权教给主程序,让他分配其他协程执行。) await 只能在带有 async 关键字的函数中运行。
- 3, asynico.run() 运行程序
- 4, 这个程序消耗时间 2s 左右。
增加协程
再添加一个任务:
task2 = visit_url('http://another.com', 3)
asynicio.run(task2)
这 2 个程序一共消耗 5s 左右的时间。并没有发挥并发编程的优势。如果是并发编程,这个程序只需要消耗 3s,也就是task2的等待时间。要想使用并发编程形式,需要把上面的代码改一下。
import asyncio
import time
async def visit_url(url, response_time):
"""访问 url"""
await asyncio.sleep(response_time)
return f"访问{url}, 已得到返回结果"
async def run_task():
"""收集子任务"""
task = visit_url('http://wangzhen.com', 2)
task_2 = visit_url('http://another', 3)
await asyncio.run(task)
await asyncio.run(task_2)
asyncio.run(run_task())
print(f"消耗时间:{time.perf_counter() - start_time}")
asyncio.gather 会创建 2 个子任务,当出现 await 的时候,程序会在这 2 个子任务之间进行调度。
create_task
创建子任务除了可以用 gather 方法之外,还可以使用 asyncio.create_task 进行创建。
async def run_task():
coro = visit_url('http://wangzhen.com', 2)
coro_2 = visit_url('http://another.com', 3)
task1 = asyncio.create_task(coro)
task2 = asyncio.create_task(coro_2)
await task1
await task2
协程的主要使用场景
协程的主要应用场景是 IO 密集型任务,总结几个常见的使用场景:
- 网络请求,比如爬虫,大量使用 aiohttp
- 文件读取, aiofile
- web 框架, aiohttp, fastapi
- 数据库查询, asyncpg, databases
进一步学习方向(接下来的文章)
- 什么时候用协程,什么时候用多线程,什么时候用多进程
- future 对象
- asyncio 的底层 api
- loop
- trio 第三方库用法
参考文献
python教程:使用 async 和 await 协程进行并发编程的更多相关文章
- python——asyncio模块实现协程、异步编程
我们都知道,现在的服务器开发对于IO调度的优先级控制权已经不再依靠系统,都希望采用协程的方式实现高效的并发任务,如js.lua等在异步协程方面都做的很强大. Python在3.4版本也加入了协程的概念 ...
- python 异步IO(syncio) 协程
python asyncio 网络模型有很多中,为了实现高并发也有很多方案,多线程,多进程.无论多线程和多进程,IO的调度更多取决于系统,而协程的方式,调度来自用户,用户可以在函数中yield一个状态 ...
- python 异步IO( asyncio) 协程
python asyncio 网络模型有很多中,为了实现高并发也有很多方案,多线程,多进程.无论多线程和多进程,IO的调度更多取决于系统,而协程的方式,调度来自用户,用户可以在函数中yield一个状态 ...
- python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用
python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用 一丶单线程+多任务的异步协程 特殊函数 # 如果一个函数的定义被async修饰后,则该函数就是一个特殊的函数 async ...
- Python之线程、进程和协程
python之线程.进程和协程 目录: 引言 一.线程 1.1 普通的多线程 1.2 自定义线程类 1.3 线程锁 1.3.1 未使用锁 1.3.2 普通锁Lock和RLock 1.3.3 信号量(S ...
- python自动化开发学习 进程, 线程, 协程
python自动化开发学习 进程, 线程, 协程 前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...
- python day 20: 线程池与协程,多进程TCP服务器
目录 python day 20: 线程池与协程 2. 线程 3. 进程 4. 协程:gevent模块,又叫微线程 5. 扩展 6. 自定义线程池 7. 实现多进程TCP服务器 8. 实现多线程TCP ...
- 11.python3标准库--使用进程、线程和协程提供并发性
''' python提供了一些复杂的工具用于管理使用进程和线程的并发操作. 通过应用这些计数,使用这些模块并发地运行作业的各个部分,即便是一些相当简单的程序也可以更快的运行 subprocess提供了 ...
- asyncio协程与并发
并发编程 Python的并发实现有三种方法. 多线程 多进程 协程(生成器) 基本概念 串行:同时只能执行单个任务 并行:同时执行多个任务 在Python中,虽然严格说来多线程与协程都是串行的,但其效 ...
随机推荐
- 贵州省网络安全知识竞赛团体赛Writeup-phpweb部分
0x01 混淆后门#conn.php 首先还是拖到D盾扫描 打开conn.php发现底部有那么一串代码: 对这个代码进行分析 首先可以对几个比较简单的变量输出看一下 $s输出内容为create_fun ...
- 什么是EIP、ESP、EBP
堆栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表.允许插入或删除操作的一端称为栈顶,另一端称为栈底,对堆栈的插入和删除操作被称入栈和出栈.有一组CPU指令可以实现对进程的内存实现堆 ...
- 软件版本管理工具-SVN
一.SVN简介 Subversion(svn)是一款开发源代码的版本控制系统. repository(源代码库):源代码统一存放的地方 Checkout(检出):当你手上没有源代码的时候,你需要从re ...
- 题解 P4325 【[COCI2006-2007#1] Modulo】
第\(1\)种方法 也是最暴力的一种 我们熟知,\(c++\)中的\(set\)可以既去重,有排序,这题,我们可以用set来搞,虽然我们不需要排序的功能,但毕竟方便,一共是\(10\)个数,所以暴力一 ...
- python-文本字符串
2019-12-05 14:41:36 一.Unicode 编码问题一直都是文本处理的时候的大难题,python2中的编码异常混乱,本章节主要讨论python3中的编码情况. python3 str的 ...
- TensorFlow系列专题(八):七步带你实现RNN循环神经网络小示例
欢迎大家关注我们的网站和系列教程:http://panchuang.net/ ,学习更多的机器学习.深度学习的知识! [前言]:在前面的内容里,我们已经学习了循环神经网络的基本结构和运算过程,这一小节 ...
- Prism+MaterialDesign+EntityFramework Core+Postgresql WPF开发总结 之 基础篇
本着每天记录一点成长一点的原则,打算将目前完成的一个WPF项目相关的技术分享出来,供团队学习与总结. 总共分三个部分: 基础篇主要争对C#初学者,巩固C#常用知识点: 中级篇主要争对WPF布局与美化, ...
- inux上安装mysql
目录 1.先验证是否安装了mysql 2.先下载mysql的repo源 3.安装mysql rpm包,执行命令: 4.安装mysql,执行命令: 5.登录然后重置密码,执行: 6.执行命令赋权,重启m ...
- 数据分析_numpy_基础2
数据分析_numpy_基础2 sqrt 开方 arr = np.arange(10) arr # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) np.sqrt(arr) ...
- 模块 time datetime 时间获取和处理
模块_time 和时间有关系的我们就要用到时间模块.在使用模块之前,应该首先导入这个模块. 1 延时 time.sleep(secs) (线程)推迟指定的时间运行.单位为秒. 2 获取当前时间戳tim ...