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

Python3中OSError [WinError 10038]错误求助:非套接字操作问题

WinError 10038 错误修复:操作非套接字对象

我找不到该问题的可行解决方案,因此决定重新提问。

错误信息

Traceback (most recent call last):
File "C:\New\pythonProject1\client.py", line 15, in
read_sockets, write_socket, error_socket = select.select(sockets_list, [], [])
OSError: [WinError 10038] An operation was attempted on something that is not a socket

问题代码

import socket
import select
import sys

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
    print("正确用法:脚本名 IP地址 端口号")
    exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.connect((IP_address, Port))

while True:
    sockets_list = [sys.stdin, server]
    read_sockets, write_socket, error_socket = select.select(sockets_list, [], [])
    for socks in read_sockets:
        if socks == server:
            message = socks.recv(2048)
            print(message)
        else:
            message = sys.stdin.readline()
            server.send(message)
            sys.stdout.write("<You>")
            sys.stdout.write(message)
            sys.stdout.flush()
server.close()

问题原因

Windows系统下的select.select()函数仅支持套接字对象,而代码里把sys.stdin(文件对象)加入了监听列表,违反了Windows平台的限制,因此触发WinError 10038错误。Linux/macOS的select支持文件描述符,但Windows的实现存在这个差异。

解决方案

方案1:用线程分离输入与套接字监听

单独开线程处理用户输入,主线程专注接收服务器消息,避免用select处理非套接字对象:

import socket
import sys
import threading

def receive_messages(server_socket):
    while True:
        try:
            message = server_socket.recv(2048)
            if not message:
                print("服务器已断开连接")
                server_socket.close()
                break
            print(message.decode('utf-8'))
        except Exception as e:
            print(f"接收消息出错:{e}")
            server_socket.close()
            break

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
    print("正确用法:脚本名 IP地址 端口号")
    exit()
IP_address = sys.argv[1]
Port = int(sys.argv[2])

try:
    server.connect((IP_address, Port))
except Exception as e:
    print(f"连接服务器失败:{e}")
    exit()

# 启动接收消息的线程
recv_thread = threading.Thread(target=receive_messages, args=(server,))
recv_thread.daemon = True
recv_thread.start()

# 主线程处理用户输入
while True:
    message = sys.stdin.readline().strip()
    if not message:
        continue
    try:
        server.send(message.encode('utf-8'))
        print(f"<You> {message}")
    except Exception as e:
        print(f"发送消息出错:{e}")
        server.close()
        break

方案2:改用selectors模块(推荐跨平台)

selectors是Python的高级IO多路复用工具,会自动适配不同平台的实现,Windows下可正确处理文件对象和套接字:

import socket
import sys
import selectors

sel = selectors.DefaultSelector()

def read_server(server_socket):
    message = server_socket.recv(2048)
    if message:
        print(message.decode('utf-8'))
    else:
        print("服务器已断开")
        sel.unregister(server_socket)
        server_socket.close()

def read_stdin(stdin):
    message = stdin.readline().strip()
    if message:
        server.send(message.encode('utf-8'))
        print(f"<You> {message}")

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
    print("正确用法:脚本名 IP地址 端口号")
    exit()
IP_address = sys.argv[1]
Port = int(sys.argv[2])

try:
    server.connect((IP_address, Port))
except Exception as e:
    print(f"连接失败:{e}")
    exit()

# 注册套接字和标准输入
sel.register(server, selectors.EVENT_READ, read_server)
sel.register(sys.stdin, selectors.EVENT_READ, read_stdin)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:55:23