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

