我使用 Python 中的 requests 库发送 POST 请求,同时维护与 websockets 库的 WebSocket 连接:
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():
s = requests.Session()
print(1)
try:
response = s.post('http://192.168.1.4/create', timeout=10)
print(3)
print(response.text)
except requests.exceptions.Timeout:
print("The request timed out") # this happens
except requests.exceptions.RequestException 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())
服务器日志显示没有请求。服务器可访问且配置正确。使用带有 Websocket 的请求时可能会导致此问题的原因是什么?
问题在于你在异步代码中使用了同步请求库
requests
。
requests.post
是一个阻塞调用,这意味着它会暂停你的事件循环,直到请求完成,从而阻止 WebSocket 处理程序接收消息。
你有几个选择可以解决这个问题:
1. 使用异步 HTTP 库:
将
requests
替换为像
aiohttp
这样的异步 HTTP 库,它允许你进行非阻塞请求:
```python import asyncio import aiohttp import websockets
async def websocket_handler(uri): # ...
async def make_request(): async with aiohttp.ClientSession() as session: 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 Exception as e: print(f"An error occurred: {e}")
async def main(): # ... ```
2. 在单独的线程中运行
requests
:
如果你不想切换到异步 HTTP 库,你可以在单独的线程中运行阻塞
requests.post
调用:
```python import asyncio import requests import websockets from concurrent.futures import ThreadPoolExecutor
async def websocket_handler(uri): # ...
def blocking_request(): try: response = requests.post('http://192.168.1.4/create', timeout=10) print(3) print(response.text) except requests.exceptions.Timeout: print("The request timed out") except requests.exceptions.RequestException as e: print(f"An error occurred: {e}")
async def make_request(): loop = asyncio.get_running_loop() with ThreadPoolExecutor() as pool: await loop.run_in_executor(pool, blocking_request)
async def main(): # ... ```
这会将阻塞调用卸载到线程池,允许事件循环继续运行,并且 WebSocket 处理程序可以接收消息。
选择哪种方法取决于你的具体需求和偏好。如果你正在构建一个需要处理大量并发请求的应用程序,那么使用
aiohttp
等异步 HTTP 库通常是更好的选择。但是,如果你只需要进行一些偶尔的请求,那么在单独的线程中运行
requests
可能更简单。