同时使用requests与websockets时Python POST请求挂起问题排查
问题原因及解决方案
核心原因
requests是同步阻塞式的HTTP库,它的所有IO操作都会直接占用当前线程。而你在asyncio的异步函数make_request里调用s.post()时,会彻底卡住asyncio的事件循环——因为asyncio基于单线程调度,同步阻塞操作会霸占整个线程,导致WebSocket连接的维护、请求本身的网络IO都无法被事件循环调度处理,最终请求超时,服务器甚至没收到完整的请求。
解决方法
方法一:改用异步HTTP库(推荐)
使用专为asyncio设计的aiohttp替代requests,它的异步IO不会阻塞事件循环,能和websockets完美配合:
import asyncio import aiohttp import websockets async def websocket_handler(uri): async with websockets.connect(uri) as websocket: while True: message = await websocket.recv() print(f"Received message: {message}") async def make_request(): async with aiohttp.ClientSession() as session: print(1) try: async with session.post('http://192.168.1.4/create', timeout=10) as response: print(3) print(await response.text()) except asyncio.TimeoutError: print("The request timed out") except aiohttp.ClientError as e: print(f"An error occurred: {e}") async def main(): websocket_task = asyncio.create_task(websocket_handler("ws://example.com/websocket")) request_task = asyncio.create_task(make_request()) await asyncio.gather(websocket_task, request_task) if __name__ == "__main__": asyncio.run(main())
方法二:将同步请求放到单独线程执行
如果必须保留requests,可以用asyncio.to_thread把同步的POST请求放到独立线程中运行,避免阻塞事件循环:
import asyncio import requests import websockets async def websocket_handler(uri): async with websockets.connect(uri) as websocket: while True: message = await websocket.recv() print(f"Received message: {message}") async def make_request(): def sync_post(): s = requests.Session() print(1) try: response = s.post('http://192.168.1.4/create', timeout=10) print(3) return response.text except requests.exceptions.Timeout: return "The request timed out" except requests.exceptions.RequestException as e: return f"An error occurred: {e}" result = await asyncio.to_thread(sync_post) print(result) async def main(): websocket_task = asyncio.create_task(websocket_handler("ws://example.com/websocket")) request_task = asyncio.create_task(make_request()) await asyncio.gather(websocket_task, request_task) if __name__ == "__main__": asyncio.run(main())
内容的提问来源于stack exchange,提问作者user23470475
相关产品推荐
相关产品推荐

