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

Pico W+MicroPython用_thread实现WebServer与数据处理并行的问题

问题与解决方案:Pico W MicroPython 并行Web服务器与数据处理

遇到的问题

  • 问题1:使用_thread运行Web服务器和数据处理函数时,Web服务器会挂起,直到数据处理函数执行完毕才响应浏览器请求,无法实时查看运行状态。
  • 问题2:运行Web服务器时,数据处理函数中的urequests.get抛出[Errno 103] ECONNABORTED错误,无法正常发起HTTP请求。

原问题代码

import utime, machine, urequests, json, network, socket, _thread

led = machine.Pin("LED", machine.Pin.OUT)

def connect():
    global wlan
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect("SSID", "PASSS")
    while wlan.isconnected() == False:
        print("Connecting...")
        led.off()
        utime.sleep_ms(100)
        led.on()
        utime.sleep_ms(100)
        led.off()
        utime.sleep_ms(100)
        led.on()
        utime.sleep_ms(100)
    led.on()
    ip = wlan.ifconfig()[0]
    print(f'Connected on {ip}')
    return ip

def open_socket(ip):
    address = (ip, 80)
    connection = socket.socket()
    connection.bind(address)
    connection.listen(1)
    return connection

def webpage(steps):
    html = f"""
            <!DOCTYPE html>
            <html>
            <head>
            <title>Pico 2</title>
            </head>
            <body>
            <p>{steps}</p>
            </body>
            </html>
            """
    return str(html)

def pushgetdata():
    while wlan.isconnected() == True:
        try:
            global steps
            led.off()
            utime.sleep_ms(300)
            led.on()
            steps = "Step 1: Reading values from sensor one...<br>"
            #function to read data from one sensor here
            #...
            #...
            #...
            led.off()
            utime.sleep_ms(100)
            led.on()
            steps = steps + "Step 2: Reading values from sensor two...<br>"
            #function to read data from other sensor here
            #...
            #...
            #...
            led.off()
            utime.sleep_ms(100)
            led.on()
            steps = steps + "Step 3: Pushing and getting results...<br>"
            jsondata = urequests.get("https://xxx.xxx.xxx/api/?device=pico2&sensor1=valulesfromsensor1&sensor2=valuesfromsensor2")
            proceseddata = jsondata.json()
            steps = steps + proceseddata + "<br>"
            steps = steps + "Step 4: Doing things with results...<br>"
            #function to do conditions and things with results...
            #...
            #...
            #...
            jsondata.close()
            steps = steps + "Step 5: Finished, sleeping for the next round...<br>"
            utime.sleep_ms(100)
            led.off()
            utime.sleep_ms(100)
            led.on()
            utime.sleep(900)
        except OSError as e:
            steps = steps + e
        

def serve(connection):
    while True:
        try:
            client, addr = connection.accept()
            print('client connected from', addr)
            request = client.recv(1024)
            request = str(request)       
            html = webpage(steps)
            client.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
            client.send(html)
            client.close()
        except OSError as e:
            client.close()
            

def webserver():
    ip = connect()
    connection = open_socket(ip)
    _thread.start_new_thread(serve,(connection,))


try:
    webserver()
    pushgetdata()
except KeyboardInterrupt:
    machine.reset()

问题1解决方案:线程阻塞与实时响应修复

核心问题

原代码中pushgetdata的utime.sleep(900)是长阻塞睡眠,会占据主线程,导致MicroPython的线程调度无法及时切换到Web服务器线程;同时全局变量steps的并发读写可能出现数据不一致。

修改要点

  1. 拆分长睡眠:把utime.sleep(900)拆分为多次短睡眠,给线程切换留足时机
  2. 线程安全锁:用_thread.allocate_lock()保护steps变量的读写操作

修改后关键代码

# 全局锁,保护steps变量的并发访问
lock = _thread.allocate_lock()
steps = ""

def pushgetdata():
    global steps
    while wlan.isconnected() == True:
        try:
            # 写入steps时加锁
            with lock:
                steps = "Step 1: Reading values from sensor one...<br>"
            led.off()
            utime.sleep_ms(300)
            led.on()
            # 传感器读取逻辑...
            
            with lock:
                steps += "Step 2: Reading values from sensor two...<br>"
            led.off()
            utime.sleep_ms(100)
            led.on()
            # 传感器读取逻辑...
            
            with lock:
                steps += "Step 3: Pushing and getting results...<br>"
            # 后续请求逻辑...
            
            with lock:
                steps += "Step 5: Finished, sleeping for the next round...<br>"
            led.off()
            utime.sleep_ms(100)
            led.on()
            # 拆分900秒睡眠为9000次100ms睡眠,触发线程切换
            for _ in range(9000):
                utime.sleep_ms(100)
        except OSError as e:
            with lock:
                steps += str(e) + "<br>"

def serve(connection):
    global steps
    while True:
        try:
            client, addr = connection.accept()
            print('client connected from', addr)
            request = client.recv(1024)
            request = str(request)
            # 读取steps时加锁
            with lock:
                html = webpage(steps)
            client.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
            client.send(html)
            client.close()
        except OSError as e:
            client.close()

问题2解决方案:urequests连接中止错误修复

核心原因

MicroPython网络栈资源有限,Web服务器监听与urequests请求可能存在资源竞争;同时无超时设置的请求容易被远端中止。

修复要点

  1. 添加请求超时:给urequests.get设置超时参数,避免长时间阻塞
  2. 自动管理连接:用with语句自动关闭响应对象,避免资源泄漏
  3. 调整线程启动顺序:让Web服务器线程在主线程运行,数据处理在子线程,优化资源调度

修改后关键代码

# 调整主逻辑的线程启动顺序
try:
    ip = connect()
    connection = open_socket(ip)
    # 先启动数据处理子线程,主线程运行Web服务器
    _thread.start_new_thread(pushgetdata, ())
    serve(connection)
except KeyboardInterrupt:
    machine.reset()

# 修改pushgetdata中的请求逻辑
with urequests.get("https://xxx.xxx.xxx/api/?device=pico2&sensor1=valulesfromsensor1&sensor2=valuesfromsensor2", timeout=5) as jsondata:
    proceseddata = jsondata.json()
    with lock:
        steps += str(proceseddata) + "<br>"
        steps += "Step 4: Doing things with results...<br>"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:30:56