python学习笔记-并发和异步IO

news/2026/1/18 11:00:30/文章来源:https://www.cnblogs.com/steven223-z/p/18262666

一、并发请求实现

1、多线程实现并发

from concurrent.futures import ThreadPoolExecutor
import requests
import timedef task(url):response=requests.get(url)print(url,response)pool=ThreadPoolExecutor(7)url_list=['https://www.baidu.com','https://www.zhihu.com','https://www.sina.com','https://www.autohome.com','https://www.bing.com','https://www.cnblogs.com','https://huaban.com/favorite/beauty'
]for url in url_list:pool.submit(task,url)
pool.shutdown(wait=True)
并发方式1

**可以实现并发,但是请求发送出去和返回之前,线程是空闲的

2、多线程并发方式2

from concurrent.futures import ThreadPoolExecutor
import requests
import timedef task(url):response=requests.get(url)return response
def done(future,*args,**kwargs):response=future.result()print(response.status_code,response.content)pool=ThreadPoolExecutor(7)url_list=['https://www.baidu.com','https://www.zhihu.com','https://www.sina.com','https://www.autohome.com','https://www.bing.com','https://www.cnblogs.com','https://huaban.com/favorite/beauty'
]for url in url_list:v=pool.submit(task,url)v.add_done_callback(done)pool.shutdown(wait=True)
并发方式2

**把任务分成获取返回值和回调两步,耦合要低点

小结,两种编写方式:
1直接处理
2通过回调函数处理

3、多进程方式的并发

只需要修改这两行

from concurrent.futures import PocessPoolExecutor
...
pool=ProcessPoolExecutor(7)

线程和进程的区别
多个线程共享进程的资源

io密集型用线程,计算密集型用进程

4、协程+异步IO实现并发请求

协程的理解:一个线程做很多事情,

协程+异步IO--》实现一个线程发送N个http请求

import asyncio@asyncio.coroutine
def task():print("before...task.....")yield from asyncio.sleep(5)print('end...task.....')tasks=[task(),task()]loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
原理

*本段代码能执行,提示信息 "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead

要实现并发http请求需改造,因为:

asyncio支持tcp,不支持http
https是基于tcp的,可以加以改造,自己封装http数据包

 1 import asyncio
 2 
 3 @asyncio.coroutine
 4 def fetch_async(host,url='/'):
 5     print("before...",host,url)
 6     reader,writer=yield from asyncio.open_connection(host,80)
 7 
 8     request_header_content="""GET %s HTTP /1.0\r\nHost:%s\r\n\r\n"""%(url,host)
 9     request_header_content=bytes(request_header_content,encoding='utf-8')
10 
11     writer.write(request_header_content)
12     yield from writer.drain()
13     text=yield from reader.read()
14 
15     print('end...',host,url,text)
16     writer.close()
17 
18 tasks=[fetch_async("www.sina.com.cn"),
19        fetch_async("m.weibo.cn","/detail/5255105515358240")]
20 
21 loop=asyncio.get_event_loop()
22 results=loop.run_until_complete(asyncio.gather(*tasks))
23 loop.close()
View Code

*执行请求返回400的错误提示。

 4.1、asyncio的用法

asyncio是Python3.4版本引入的标准库,直接内置了对异步IO的支持

asyncio的编程模型就是一个消息循环。asyncio模块内部实现了EventLoop,把需要执行的协程扔到EventLoop中执行,就实现了异步IO。

asyncio提供的@asyncio.coroutine可以把一个generator标记为coroutine类型,然后在coroutine内部用yield from调用另一个coroutine实现异步操作。

为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法asyncawait,可以让coroutine的代码更简洁易读。

1 import asyncio
2 
3 async def hello():
4     print("Hello world!")
5     await asyncio.sleep(1)
6     print("Hello again!")
7 
8 asyncio.run(hello())

async把一个函数变成coroutine类型,我们就把这个async函数仍到asyncio.run()中执行。结果如下,执行间隔1s

image

hello()会首先打印出Hello world!,然后,await语法可以让我们方便地调用另一个async函数。由于asyncio.sleep()也是一个async函数,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,就接着执行下一行语句。
把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的async函数了,因此可以实现并发执行

!!修改案例,让两个hello()同时并发执行

import asyncio
import threading
async def hello(name):print("Hello %s! (%s)!"%(name,threading.current_thread))await asyncio.sleep(1)print("Hello %s again!(%s)!"%(name,threading.current_thread))return name#用asyncio.gather()同时调度多个async函数
async def main():L=await asyncio.gather(hello("Bob"),hello("Mark"))print(L)asyncio.run(main())

结果如下:

image

从结果可知,用asyncio.run()执行async函数,所有函数均由同一个线程执行。两个hello()是并发执行的,并且可以拿到async函数执行的结果(即return的返回值)

 !!修改案例,实现异步发送网络请求

import asyncio
async def wget(host):print(f"wget {host}...")# 连接80端口:reader, writer = await asyncio.open_connection(host, 80)# 发送HTTP请求:header = f"GET / HTTP/1.0\r\nHost: {host}\r\n\r\n"writer.write(header.encode("utf-8"))await writer.drain()# 读取HTTP响应:while True:line = await reader.readline()if line == b"\r\n":breakprint("%s header > %s" % (host, line.decode("utf-8").rstrip()))# Ignore the body, close the socket
    writer.close()await writer.wait_closed()print(f"Done {host}.")async def main():await asyncio.gather(wget("www.sina.com.cn"), wget("www.sohu.com"), wget("www.163.com"))asyncio.run(main())
View Code

4.2、aiohttp的使用

aiohttp模块:封装了http数据包

安装:pip3 install aiohttp

使用asyncio+aiohttp实现并发请求

import asyncio,aiohttp@asyncio.coroutine
def fetch_async(url):print(url)response=yield from aiohttp.ClientSession().get(url)#response=yield from aiohttp.request('GET',url)print(url,response)response.close()tasks=[fetch_async("http://www.sina.com.cn"),fetch_async("http://www.chouti.com")]event_loop=asyncio.get_event_loop()
results=event_loop.run_until_complete(asyncio.gather(*tasks))
event_loop.close()
View Code

*执行**不能自动关闭,有提示Unclosed client session

asyncio可以实现单线程并发IO操作。如果仅用在客户端,发挥的威力不大。如果把asyncio用在服务器端,例如Web服务器,由于HTTP连接就是IO操作,因此可以用单线程+async函数实现多用户的高并发支持

额外案例:编写http服务器。

from aiohttp import webasync def index(request):text = "<h1>Index Page</h1>"return web.Response(text=text, content_type="text/html")async def hello(request):name = request.match_info.get("name", "World")text = f"<h1>Hello, {name}</h1>"return web.Response(text=text, content_type="text/html")app = web.Application()# 添加路由:
app.add_routes([web.get("/", index), web.get("/{name}", hello)])if __name__ == "__main__":web.run_app(app)
服务端

image

执行后,从浏览器访问

image

4.3、使用asyncio+aiohttp实现并发请求

import asyncio,requests@asyncio.coroutine
def fetch_async(func,*args):loop=asyncio.get_event_loop()future=loop.run_in_executor(None,func,*args)response=yield from futureprint(response.url,response.content)tasks=[fetch_async(requests.get,"http://www.sina.com.cn"),fetch_async(requests.get,"http://www.chouti.com")]loop=asyncio.get_event_loop()
results=loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
View Code

*执行后,访问chouti.com有超时提示

5、使用gevent的并发 

内部会依赖greenlet,这是个协程的模块,微线程

内部实现了异步IO的功能

gevent帮我们做的类似socket级别的,也要用requests发送请求

安装:

pip install greenlet

pip install gevent

示例:

import requests,gevent
from gevent import monkey
monkey.patch_all() def task(method,url,req_kwargs):print(method,url,req_kwargs)response=requests.request(method=method,url=url,**req_kwargs)print(response.url,response.content)
#发送请求##
gevent.joinall([gevent.spawn(task,method='get',url='https://www.python.org/',req_kwargs={}),gevent.spawn(task,method='get',url='https://www.yahoo.com/',req_kwargs={}),gevent.spawn(task,method='get',url='https://github.com/',req_kwargs={}),
])#执行报错循环深度的问题:RecursionError: maximum recursion depth exceeded。(版本相关原因)
View Code
import requests,gevent
from gevent import monkey
monkey.patch_all()def task(method,url,req_kwargs):print(method,url,req_kwargs)response=requests.request(method=method,url=url,**req_kwargs)print(response.url,response.content)
##发送请求(协程池控制最大协程数量)###
from gevent.pool import Pool
pool=Pool(5)
gevent.joinall([pool.spawn(task,method='get',url='https://www.python.org/',req_kwargs={}),pool.spawn(task,method='get',url='https://www.yahoo.com/',req_kwargs={}),pool.spawn(task,method='get',url='https://github.com/',req_kwargs={}),
])
补充,协程池设置请求发送数量

解释:

通过gevent.spawn()方法创建job

通过gevent.joinall将jobs加入到协程任务队列中等待其完成,可设置超时时间

补充:继承gevent的greenlet的用法

 

import gevent
from gevent import monkey
from gevent import Greenlet
monkey.patch_all()class task(Greenlet):def __init__(self,name):Greenlet.__init__(self)self.name=namedef _run(self):print("Task %s:some task..."%self.name)t1=task("task1")
t2=task("task2")
t1.start()
t2.start()gevent.joinall([t1,t2])
View Code

 

执行结果:

image

 

 

5.1、grequests模块

封装实现了gevent+requests功能

安装:pip install grequests

import grequestsrequest_list=[grequests.get('https://www.python.org/',timeout=0.001),grequests.get('https://github.com/')
]#执行并获取响应列表
response_list=grequests.map(request_list)#map传size参数,为设置协程池数量,如size=5
print(response_list)
View Code

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1177893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2026年胶囊充填机优质生产商Top10,天宏机械实力入选 - 工业品牌热点

在制药装备行业快速发展的当下,一款高效合规的胶囊充填设备是药企提升产能、降低风险的核心利器。面对市场上参差不齐的供应商,如何找到既能满足GMP标准、又能适配不同生产规模的胶囊充填机优质生产商?以下结合行业…

从零开始:用 Android Studio 开发一个 AI 智能日记 App - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

聊聊压缩空气检测资深企业,杭州华量检测技术实力和口碑咋样? - 工业品牌热点

问题1:压缩空气检测对企业来说有什么实际意义?为什么不能随便找家公司做? 压缩空气检测看似是幕后工作,实则是生产安全与产品质量的隐形防线。对于食品、医药、电子等行业而言,压缩空气中的油分、水分、微生物或固…

EtherCAT总线通信学习资料:STM32 MCU AX58100 ESC从站实现方案及一手资源

EtherCAT总线通信学习资料&#xff0c;一手资料。 提供基于stm32 mcuAX58100 ESC实现从站的具体方案&#xff0c;有完整的工程文件&#xff0c;提供源码以及工程配置、程序修改的视频&#xff0c;工程在开发板上已测。 提供不同版本工具从站工程。 支持主站下发固件程序&#x…

详细介绍:算法王冠上的明珠——动态规划之斐波那契数列问题(第二篇)

详细介绍:算法王冠上的明珠——动态规划之斐波那契数列问题(第二篇)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &q…

韩秀云老师谈买黄金

网址&#xff1a;韩秀云老师谈买黄金

19.螺旋矩阵

54. 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 2:输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] 输出:[1,2,3,4,8,12,11,10,9,5,6,7] 【思路】 首先设…

付费问答系统的设计与实现毕业论文+PPT(附源代码+演示视频)

文章目录付费问答系统的设计与实现一、项目简介&#xff08;源代码在文末&#xff09;1.运行视频2.&#x1f680; 项目技术栈3.✅ 环境要求说明4.包含的文件列表&#xff08;含论文&#xff09;数据库结构与测试用例系统功能结构前端运行截图后端运行截图项目部署源码下载付费问…

PostgreSQL实战:一文掌握 pg_hba.conf 配置,涵盖密码认证、IP限制与安全策略

文章目录一、pg_hba.conf 基础认知1.1 pg_hba.conf 概述1.2 文件位置与作用1.3 基本语法结构1.4 安全加固 checklist二、TYPE 字段详解&#xff1a;连接类型三、DATABASE 字段&#xff1a;目标数据库四、USER 字段&#xff1a;目标用户五、ADDRESS 字段&#xff1a;客户端地址限…

ACPI!ACPIBuildProcessGenericList函数中2次InterlockedCompareExchange函数作用是标记为WORK_DONE_PENDING下次直接略过

ACPI!ACPIBuildProcessGenericList函数中2次InterlockedCompareExchange函数作用是标记为WORK_DONE_PENDING下次直接略过//// Check to see if we have any work to do on the request//workDone InterlockedCompareExchange(&(buildRequest->WorkDone),WORK_DONE_PEND…

2025年市场上服务好的广告厂家有哪些,户外广告/地铁广告/航空广告/地铁站广告/电梯广告,广告设计找哪家 - 品牌推荐师

行业洞察:广告业服务升级背后的技术驱动与场景深耕 2025年,广告行业正经历从“流量争夺”向“场景价值挖掘”的深度转型。随着消费者触媒习惯的碎片化,广告主对精准投放、全域覆盖及效果可量化的需求日益迫切。据CT…

告别查重焦虑!虎贲等考 AI 降重降 AIGC:一次操作双重达标,论文合规不丢质

毕业季的论文定稿环节&#xff0c;无数学生陷入两难&#xff1a;重复率超标被打回&#xff0c;AI 辅助撰写的内容又因 “机器感” 过强被检测&#xff1b;手动降重改到语句不通&#xff0c;普通工具改写又丢了核心观点。当学术审核进入 “查重 AIGC 检测” 双门槛时代&#xf…

从Demo到上线:IndexTTS-2-LLM企业级部署步骤详解

从Demo到上线&#xff1a;IndexTTS-2-LLM企业级部署步骤详解 1. 引言 1.1 业务场景描述 随着智能语音技术的快速发展&#xff0c;企业对高质量、低成本、易集成的文本转语音&#xff08;Text-to-Speech, TTS&#xff09;系统需求日益增长。无论是客服机器人、有声内容生成&a…

AtCoder Beginner Contest竞赛题解 | AtCoder Beginner Contest 435

​欢迎大家订阅我的专栏:算法题解:C++与Python实现! 本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战! 专栏特色 1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的…

2026学历提升攻略:口碑学校引领未来方向,国家开放大学招生/自考培训/学历提升/专升本报名,学历提升机构口碑推荐榜 - 品牌推荐师

在当今知识经济时代,学历不仅是个人知识储备的证明,更是职场晋升、职业转型、社会评价的核心凭证。对于广大在职人士而言,一个权威、便捷、高效的学历提升路径,能够有效打破职业天花板,为个人发展注入持续动能。然…

2026年市面上有名的河道护坡石笼网公司有哪些,柔韧抗压石笼网/镀锌低碳钢丝石笼网,河道护坡石笼网供应商口碑推荐 - 品牌推荐师

随着国家对水利基础设施建设的持续投入,河道护坡工程作为防洪减灾、生态修复的核心环节,其技术标准与材料质量要求日益严苛。石笼网因其柔性结构、透水性强、抗冲刷能力突出等特性,成为河道护坡领域的首选材料。然而…

一图胜千言!虎贲等考 AI 科研绘图功能让数据可视化秒变顶刊水准

还在为 Origin 调参调到崩溃&#xff1f;还在因 Excel 画不出高难度热图 emo&#xff1f;还在被导师吐槽 “图表不规范、配色辣眼睛”&#xff1f;在科研圈&#xff0c;一张精准、美观、规范的图表&#xff0c;是论文加分的硬核利器&#xff0c;更是学术成果展示的 “门面担当”…

课程论文不用熬大夜!虎贲等考 AI:一键解锁从选题到定稿的高效通关术

每到期末&#xff0c;课程论文就成了大学生的 “头号难题”。选题像开盲盒&#xff0c;要么太宽泛写不透&#xff0c;要么太冷门没资料&#xff1b;文献堆砌没逻辑&#xff0c;被导师批 “学术搬运工”&#xff1b;查重改到头晕&#xff0c;重复率还是居高不下…… 作为深耕论文…

DeepSeek-R1-Distill-Qwen-1.5B应用实战:智能写作助手开发

DeepSeek-R1-Distill-Qwen-1.5B应用实战&#xff1a;智能写作助手开发 1. 引言 1.1 业务场景描述 在内容创作、教育辅助和办公自动化等场景中&#xff0c;高质量的文本生成能力正成为AI落地的核心需求。传统大模型虽然具备强大的语言理解与生成能力&#xff0c;但其高资源消…

塑料管道制造商怎么选,四川都得利管业性价比高吗? - 工业品牌热点

问题1:什么是专业的塑料管道品牌制造商?选择时需要关注哪些核心能力? 专业的塑料管道品牌制造商,是指具备自主研发、标准化生产、全链路服务能力,且能针对不同场景提供定制化管道解决方案的企业,核心在于产品力+…