当前位置: 首页 > news >正文

Python HTTP客户端实战:从urllib到异步请求

Python HTTP客户端实战:从urllib到异步请求

引言

HTTP客户端是后端开发中不可或缺的工具,用于与外部API进行通信。Python提供了多种HTTP客户端方案,从标准库的urllib到第三方库如requests、httpx等。

本文将深入探讨Python中的HTTP客户端技术,包括同步和异步方案,并分享生产环境中的最佳实践。

一、标准库HTTP客户端

1.1 urllib.request基础用法

import urllib.request import urllib.parse # 发送GET请求 url = 'https://api.example.com/data' response = urllib.request.urlopen(url) data = response.read().decode('utf-8') print(data) # 发送POST请求 url = 'https://api.example.com/submit' data = urllib.parse.urlencode({'key': 'value'}).encode('utf-8') response = urllib.request.urlopen(url, data=data) print(response.status)

1.2 自定义请求头和代理

import urllib.request url = 'https://api.example.com/data' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Authorization': 'Bearer token123' } req = urllib.request.Request(url, headers=headers) # 设置代理 proxy_handler = urllib.request.ProxyHandler({'http': 'http://proxy.example.com:8080'}) opener = urllib.request.build_opener(proxy_handler) response = opener.open(req)

二、requests库详解

2.1 基本用法

import requests # GET请求 response = requests.get('https://api.example.com/data', params={'page': 1, 'limit': 10}) print(response.json()) # POST请求 data = {'username': 'user', 'password': 'pass'} response = requests.post('https://api.example.com/login', json=data) # 响应处理 print(response.status_code) print(response.headers) print(response.cookies)

2.2 请求会话和连接池

import requests # 创建会话对象,自动处理cookies和连接复用 session = requests.Session() session.headers.update({'Authorization': 'Bearer token'}) # 多次请求复用连接 response1 = session.get('https://api.example.com/data1') response2 = session.get('https://api.example.com/data2') # 自定义适配器配置 from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry retry_strategy = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount('https://', adapter)

2.3 文件上传和下载

import requests # 文件上传 with open('file.txt', 'rb') as f: response = requests.post( 'https://api.example.com/upload', files={'file': ('file.txt', f, 'text/plain')} ) # 大文件流式下载 url = 'https://example.com/large_file.zip' response = requests.get(url, stream=True) with open('large_file.zip', 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk)

三、异步HTTP客户端

3.1 aiohttp基础

import aiohttp import asyncio async def fetch(session, url): async with session.get(url) as response: return await response.json() async def main(): async with aiohttp.ClientSession() as session: tasks = [ fetch(session, 'https://api.example.com/data1'), fetch(session, 'https://api.example.com/data2'), fetch(session, 'https://api.example.com/data3') ] results = await asyncio.gather(*tasks) print(results) asyncio.run(main())

3.2 httpx异步客户端

import httpx import asyncio async def main(): async with httpx.AsyncClient() as client: # 并发请求 responses = await asyncio.gather( client.get('https://api.example.com/data1'), client.get('https://api.example.com/data2') ) for response in responses: print(response.json()) asyncio.run(main())

四、HTTP客户端对比

4.1 性能对比实验

import requests import httpx import time def test_requests_sync(): start = time.time() for _ in range(10): requests.get('https://httpbin.org/get') return time.time() - start def test_httpx_sync(): start = time.time() client = httpx.Client() for _ in range(10): client.get('https://httpbin.org/get') return time.time() - start print(f"requests sync: {test_requests_sync():.3f}s") print(f"httpx sync: {test_httpx_sync():.3f}s")

4.2 方案选择指南

特性urllibrequestshttpxaiohttp
易用性中等
异步支持
连接池基础优秀优秀优秀
文件上传复杂简单简单简单
代理支持支持支持支持支持

五、生产环境最佳实践

5.1 请求超时配置

import requests # 设置超时时间 try: response = requests.get( 'https://api.example.com/data', timeout=5 # 5秒超时 ) except requests.exceptions.Timeout: print("请求超时") except requests.exceptions.RequestException as e: print(f"请求失败: {e}")

5.2 错误重试机制

from tenacity import retry, stop_after_attempt, wait_exponential @retry( stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10) ) def fetch_data(url): response = requests.get(url) response.raise_for_status() return response.json() try: data = fetch_data('https://api.example.com/data') except Exception as e: print(f"重试后仍失败: {e}")

5.3 请求日志记录

import logging import requests logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def log_request(func): def wrapper(*args, **kwargs): url = args[0] if args else kwargs.get('url') logger.info(f"请求: {url}") try: response = func(*args, **kwargs) logger.info(f"响应: {response.status_code}") return response except Exception as e: logger.error(f"请求失败: {e}") raise return wrapper @log_request def safe_request(url): return requests.get(url)

六、高级HTTP客户端技术

6.1 自定义认证处理器

from requests.auth import AuthBase class BearerAuth(AuthBase): def __init__(self, token): self.token = token def __call__(self, r): r.headers['Authorization'] = f'Bearer {self.token}' return r # 使用自定义认证 response = requests.get( 'https://api.example.com/data', auth=BearerAuth('my_token') )

6.2 请求限流

import time from collections import deque class RateLimiter: def __init__(self, max_requests, time_window): self.max_requests = max_requests self.time_window = time_window self.request_times = deque() def wait(self): now = time.time() # 移除时间窗口外的请求记录 while self.request_times and now - self.request_times[0] > self.time_window: self.request_times.popleft() # 如果达到限制,等待 if len(self.request_times) >= self.max_requests: wait_time = self.time_window - (now - self.request_times[0]) time.sleep(max(0, wait_time)) self.request_times.append(time.time()) # 使用限流 limiter = RateLimiter(max_requests=100, time_window=60) for _ in range(150): limiter.wait() # 发送请求

七、总结

选择合适的HTTP客户端需要考虑:

  1. 同步vs异步:高并发场景选择异步客户端
  2. 功能需求:文件上传、代理、认证等
  3. 性能要求:连接池、重试机制
  4. 生态系统:与现有代码的兼容性

在实际项目中,推荐:

  • 简单场景使用requests
  • 异步场景使用httpx或aiohttp
  • 生产环境添加超时、重试、限流等机制

思考:在你的项目中,HTTP客户端的最大挑战是什么?欢迎分享!

http://www.jsqmd.com/news/788605/

相关文章:

  • 从Gumbel到Clayton:三维Copula模型选型避坑指南(附R代码AIC/BIC对比)
  • 别再为Quartus 18.1和Modelsim联调抓狂了!手把手教你搞定VWF前仿真(附常见错误排查)
  • 微信网页版复活指南:3分钟解决“无法登录“难题
  • 2026年好用的恒玖不干胶定制排名,靠谱吗 - myqiye
  • 【安全测试】BurpSuite 保姆级安装教程!超详细图文详解 ,零基础一键部署直接可用
  • 除了闪回,my2sql还能帮你分析MySQL里的‘大事务’和‘长事务’
  • 什么是 Linux 发行版?GNU/Linux 与 Linux kernel 有何联系?
  • 全屋定制整装源头厂家哪家好 - mypinpai
  • 可自我迭代升级数字生命工程:从记忆厮杀到自我意识觉醒全链路——AGI内生智能硅基生命心智建模(下)
  • Python异步性能调优实战
  • 对比使用Taotoken前后在模型调用成本与账单清晰度上的变化
  • VR手柄电容感应数据驱动手部骨骼动画的核心原理与工程实践
  • 告别MinGW!在Win10上用Cygwin64+VSCode搭建C/C++开发环境(保姆级图文教程)
  • Python事件驱动架构:从基础到生产实践
  • 从音频均衡器到图像滤波:聊聊LTI系统在FFmpeg和OpenCV里的那些“隐藏”应用
  • 2026年液压油管生产厂哪家可靠? - mypinpai
  • DataGrip新手必看:从连接数据库到创建Schema的保姆级图文指南
  • 告别空间FFT模糊:用MVDR波束形成在Python/MATLAB中实现高分辨率DOA估计(附完整代码)
  • 模仿学习中的模糊性问题与专家乘积负反馈系统设计
  • 基于MCP协议与DrissionPage构建AI原生网页自动化工具链
  • 告别论文焦虑!百考通AI带你五步搞定本科毕业设计
  • 终极解决方案:如何让微信网页版在浏览器中重新工作
  • 【汽车芯片功能安全分析与故障注入实践 07】Endpoint FIT Contribution:如何找到最值得保护的节点?
  • Agent Checkpoint:为AI编程助手构建可验证的工程化协作流程
  • 靠谱的高压油管厂家推荐,景县昌阳橡塑 - mypinpai
  • 易语言大漠插件实战:从零构建游戏字库与Ocr精准识别系统
  • 直播间高品质精选音乐素材合集
  • 文献计量学视角:AI在创业与公司金融领域的研究脉络与趋势
  • 从CSS色值到Qt界面:QColor构造函数与颜色代码的5种高效用法(含避坑点)
  • ARM高效运算指令SDIV、UDIV与SEL详解