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
相关产品推荐
相关产品推荐

