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

Python控制ESP32时报错:OSError [WinError 10038]非套接字操作

解决OSError: [WinError 10038] 套接字操作错误

问题原因

你遇到的OSError: [WinError 10038] An operation was attempted on something that is not a socket错误,根源在于socket的使用逻辑:

  • 全局创建了一个sock对象,每次调用tr()函数发送指令后,直接调用sock.close()关闭了这个套接字。
  • 当第二次检测到蓝色物体再次调用tr('R')时,尝试用已经被关闭的socket对象执行connect()操作,此时该socket已不再是有效的资源,因此触发错误。

解决方案

提供两种可行的修改方案,根据你的使用场景选择:

方案1:每次发送指令创建新Socket(适合低频率指令场景)

修改tr函数,将socket的创建、连接、发送、关闭逻辑都放在函数内部,避免复用已关闭的socket:

def tr(s):
    # 每次调用时新建socket实例
    sock = socket.socket()
    try:
        sock.connect((host, port))
        sock.send(s.encode('utf-8'))
    finally:
        # 确保无论是否发送成功,都关闭socket
        sock.close()

方案2:保持长连接(适合高频率指令场景)

在程序启动时建立一次socket连接,后续直接复用该连接发送指令,仅在程序结束时关闭连接,减少连接开销:

import cv2
import numpy as np
import imutils
import socket               

host = "192.168.4.1"  # ESP32局域网IP
port = 80             # ESP32服务端口    

# 初始化并建立socket长连接
sock = socket.socket()
try:
    sock.connect((host, port))
except Exception as e:
    print(f"连接ESP32失败: {str(e)}")
    exit(1)

def tr(s):
    if s in ['L', 'R']:
        sock.send(s.encode('utf-8'))

cap = cv2.VideoCapture(0)

try:
    while True:
        _, frame = cap.read()
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        lower_blue = np.array([90,60,0])
        upper_blue = np.array([121,255,255])

        mask4 = cv2.inRange(hsv, lower_blue, upper_blue)

        cnts4 = cv2.findContours(mask4, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        cnts4 = imutils.grab_contours(cnts4)

        for c in cnts4:
            area4 = cv2.contourArea(c)
            if 5000 < area4 < 50000:
                cv2.drawContours(frame, [c], -1, (0,255,0), 3)
                tr('R')
                M = cv2.moments(c)
                cx = int(M["m10"] / M["m00"])
                cy = int(M["m01"] / M["m00"])
                cv2.circle(frame, (cx, cy), 7, (255,255,255), -1)
                cv2.putText(frame, "Blue", (cx-20, cy-20), cv2.FONT_HERSHEY_SIMPLEX, 2.5, (255,255,255), 1)
        
        cv2.imshow("result", frame)

        # 修正退出逻辑:waitKey返回ASCII码,需与ord('q')比较
        if cv2.waitKey(5) & 0xff == ord('q'):
            break
finally:
    # 程序结束时释放所有资源
    cap.release()
    cv2.destroyAllWindows()
    sock.close()

额外注意点

原代码中cv2.waitKey(5) & 0xff == 'q'存在逻辑错误,waitKey()返回的是按键的ASCII码值,应该与ord('q')比较才能正确响应退出操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:10:36