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

Python SocketIO客户端开发:如何在捕获指定事件时终止while循环

SocketIO客户端登录循环跳出实现方案

原代码存在的问题

  • 事件处理器重复注册:将sio.on装饰器写在while循环内部,每次循环都会重新注册一次事件回调,多次尝试登录后同一个事件会触发多次回调逻辑
  • 变量作用域错误:index是login函数内部定义的局部变量,回调函数中使用global关键字只能读取全局作用域变量,无法修改函数内的局部index,这也是你无法跳出循环的核心原因
  • 固定等待逻辑不合理:强制等待2秒的逻辑不管服务端有没有提前返回都会卡满时长,响应效率低,也没有超时异常处理

优化实现代码

import socketio
from threading import Event

sio = socketio.Client()
# 提前全局注册所有事件回调,避免重复注册
login_result = None
login_event = None

@sio.on('wrong username')
def handle_wrong_username():
    global login_result
    print("该用户名不存在")
    login_result = False
    if login_event:
        login_event.set()

@sio.on('wrong password')
def handle_wrong_password():
    global login_result
    print("密码错误,请重试")
    login_result = False
    if login_event:
        login_event.set()

@sio.on('connected')
def handle_login_success():
    global login_result
    print("登录成功")
    login_result = True
    if login_event:
        login_event.set()

def login():
    global login_result, login_event
    # 未连接时先连接SocketIO服务端,替换为你自己的服务端地址
    if not sio.connected:
        sio.connect('http://你的服务端地址:端口号')
    
    while True:
        username = input("请输入用户名\n")
        password = input("请输入密码\n")
        # 初始化事件对象用于同步等待服务端响应
        login_event = Event()
        login_result = None
        
        sio.emit('send user name and password', {"username": username, "password": password})
        
        # 最多等待5秒,超时自动唤醒
        is_timeout = not login_event.wait(timeout=5)
        if is_timeout:
            print("登录请求超时,请重试")
            continue
        # 登录成功直接跳出循环
        if login_result:
            break

实现说明

  • 所有事件回调提前在全局注册,不会出现重复触发的问题
  • 用threading.Event的wait方法替代固定时长sleep,服务端返回后会立刻唤醒后续逻辑,响应速度更快,同时支持自定义超时时间
  • 用全局变量传递登录状态,避开局部变量作用域无法跨回调修改的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 06:15:03