You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python requests库向RPi Pico W发送数据时常为空的原因咨询

RPi Pico W Web服务器无法接收Python requests请求数据的问题

问题描述

在RPi Pico W上运行简易Web服务器,可通过浏览器、cURL正常接收数据并返回JSON,但使用Python requests库发送PUT请求时,多数情况下数据无法传递到服务器。

请求代码

import json
import requests

data = json.dumps({"KEY":"VALUE"})
res = requests.put("http://webserver.ip:port", data=data)
print(res.json())

(注:尝试改用json={"KEY":"VALUE"}参数,问题仍存在)

Pico W服务器代码

i = 0
while True:
    client = conn.accept()[0]
    print(f"[{i}] Client connected: {client}")
    msg = client.recv(8192)
    print(f"Message: {msg}")
    data = msg.decode("utf-8").split("\r")[-1].strip()
    print(f'Data: {data}, {type(data)}, {data == ""}')
    message = {
        "data": ujson.loads(data) if data != "" else None,
        "key1": "value1",
        "key2": "value2",
        "key3": "value3",
    }
    client.send(b"HTTP/1.1 200 OK\n")
    client.send(b"Content-Type: application/json\n")
    client.send(b"Connection: keep-alive\n\n")
    client.sendall(ujson.dumps(message).encode("utf-8"))
    client.close()
    i += 1

预期返回

{"key1": "value1", "key2": "value2", "key3": "value3", "data": {"KEY":"VALUE"}}

实际返回

{"key1": "value1", "key2": "value2", "key3": "value3", "data": None}

问题原因

  1. 请求接收不完整:client.recv(8192)仅尝试一次读取数据,但requests发送的请求可能因TCP缓冲机制被拆分为多个数据包,第一次recv仅获取到请求头,未拿到body内容。而curl/浏览器的请求可能刚好一次性完成传输,因此能正常解析。
  2. HTTP请求解析错误:代码通过split("\r")[-1]提取body的方式完全不符合HTTP协议规范。HTTP请求的body是位于请求头与body分隔符\r\n\r\n之后的内容,而非简单分割\r的最后一项。
  3. 未处理分块编码:requests默认可能使用Transfer-Encoding: chunked发送请求(尤其是当请求体较大时),而当前服务器代码完全未处理这种编码格式,导致无法正确读取body。

解决办法

1. 正确解析HTTP请求,读取完整body

修改服务器代码,严格按照HTTP协议规范解析请求头与body:

import ujson

i = 0
while True:
    client = conn.accept()[0]
    print(f"[{i}] Client connected: {client}")
    
    # 循环接收直到拿到完整的请求头(找到分隔符)
    full_request = b""
    while b"\r\n\r\n" not in full_request:
        chunk = client.recv(1024)
        if not chunk:
            break
        full_request += chunk
    
    # 分割请求头和body
    if b"\r\n\r\n" not in full_request:
        # 无效请求,直接返回
        client.send(b"HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n")
        client.close()
        i += 1
        continue
    
    header_part, body_part = full_request.split(b"\r\n\r\n", 1)
    header_str = header_part.decode("utf-8")
    
    # 处理body内容
    body = b""
    if "Transfer-Encoding: chunked" in header_str:
        # 解析分块编码内容
        while b"0\r\n\r\n" not in body_part:
            chunk = client.recv(1024)
            if not chunk:
                break
            body_part += chunk
        chunks = body_part.split(b"\r\n")
        for idx in range(0, len(chunks)-2, 2):
            chunk_len = int(chunks[idx], 16)
            if chunk_len > 0:
                body += chunks[idx+1][:chunk_len]
    else:
        # 按Content-Length读取完整body
        content_length = 0
        for line in header_str.split("\r\n"):
            if line.startswith("Content-Length:"):
                content_length = int(line.split(":")[1].strip())
                break
        # 补充读取剩余的body内容
        while len(body_part) < content_length:
            chunk = client.recv(1024)
            if not chunk:
                break
            body_part += chunk
        body = body_part[:content_length]
    
    # 解析JSON数据
    data_str = body.decode("utf-8").strip()
    print(f'Data: {data_str}, {type(data_str)}, {data_str == ""}')
    
    message = {
        "data": ujson.loads(data_str) if data_str != "" else None,
        "key1": "value1",
        "key2": "value2",
        "key3": "value3",
    }
    
    # 发送响应(改用标准HTTP换行符\r\n,关闭连接避免复用问题)
    client.send(b"HTTP/1.1 200 OK\r\n")
    client.send(b"Content-Type: application/json\r\n")
    client.send(b"Connection: close\r\n\r\n")
    client.sendall(ujson.dumps(message).encode("utf-8"))
    client.close()
    i += 1

2. 临时简化请求发送(可选)

如果暂时不想修改服务器代码,可以强制requests使用Content-Length而非分块编码,减少请求拆分概率:

import requests

headers = {"Transfer-Encoding": "identity"}
res = requests.put("http://webserver.ip:port", json={"KEY":"VALUE"}, headers=headers)
print(res.json())

(注:此方法仅为临时 workaround,建议优先修改服务器代码以符合HTTP规范)


内容的提问来源于stack exchange,提问作者Parsia Hedayat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:47:11