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

PyInstaller打包Win10执行文件触发ValueError: '0' is not in list问题

问题分析

你遇到的ValueError: '0' is not in list错误,本质是Windows10打包后的EXE中,GetKeyboardLayout返回的KLID经过位运算后得到lid=0,而你的lcid字典里没有这个键,导致key_list.index(str(lid))触发报错。Windows11上正常是因为系统API在切换键盘布局时的行为差异——Win11不会返回临时的0值,而Win10在切换瞬间可能出现这个过渡状态。

另外代码还有几个潜在问题:

  • 每次触发都重新初始化pyttsx3引擎,既影响性能也可能导致资源泄漏
  • 用keyboard.on_press_key('shift')再判断Alt的方式,容易产生重复触发
  • 未处理不在预期内的LCID值,容错性不足
修复后的代码
import keyboard
import time
import ctypes
import pyttsx3
from plyer import notification

# 全局初始化语音引擎,避免重复创建
engine = pyttsx3.init()
lcid = {
    "1040": "Italian (it_IT)",
    "1033": "English (en_US)",
    "1037": "Hebrew (he_IL)",
    "2058": "Spanish (es_MX)",
}

def on_layout_switch():
    user32 = ctypes.WinDLL('user32', use_last_error=True)
    curr_window = user32.GetForegroundWindow()
    if not curr_window:
        return  # 无效窗口直接返回
    
    thread_id = user32.GetWindowThreadProcessId(curr_window, None)
    klid = user32.GetKeyboardLayout(thread_id)
    lid = klid & 0xFFFF  # 等价于2**16-1,写法更简洁
    
    lid_str = str(lid)
    # 处理lid=0的临时状态或未知布局,直接跳过
    if lid_str not in lcid:
        return
    
    # 语音播报
    lang_name = lcid[lid_str].split(' ')[0]
    engine.say(lang_name)
    engine.runAndWait()
    
    # 发送通知
    notification.notify(
        title="Language Keyboard Switch",
        message=lcid[lid_str],
        timeout=1  # 延长超时时间,确保通知能被看到
    )

# 直接监听Alt+Shift组合键,避免误触发
keyboard.add_hotkey('alt+shift', on_layout_switch)

# 保持脚本运行
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("脚本已退出")
关键修复点
  • 增加容错处理:直接跳过不在lcid中的值,避免触发索引错误
  • 全局初始化语音引擎:只创建一次引擎,提升性能和稳定性
  • 改用组合键监听:直接绑定alt+shift,代替原有的监听Shift再判断Alt的逻辑,减少重复触发
  • 优化窗口有效性检查:避免无效窗口导致的API调用异常
  • 简化位运算写法:用0xFFFF替代2**16-1,代码更直观
  • 调整通知超时:将原0.1秒延长至1秒,确保用户能看到通知内容
打包注意事项

用PyInstaller打包时,建议添加以下参数避免依赖缺失:

pyinstaller --onefile --windowed --hidden-import plyer.platforms.win.notification --hidden-import pyttsx3.drivers.sapi5 your_script.py
  • --onefile:生成单个独立EXE文件
  • --windowed:不显示控制台窗口(调试时可去掉)
  • --hidden-import:显式指定plyer和pyttsx3的隐藏依赖,防止打包后运行时找不到模块

内容的提问来源于stack exchange,提问作者Giovanni Lo Bocchiaro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:21:24