PyInstaller打包后导入winrt模块报Cannot change thread mode错误如何解决
报错原因
这个错误是WinRT模块的COM线程模型要求与PyInstaller的默认启动逻辑冲突导致的:
- PyInstaller的控制台程序加载器在进程启动时会默认将主线程的COM模式设置为MTA(多线程单元)
- winrt模块在导入时会尝试将当前线程的COM模式设置为STA(单线程单元)
- Windows规定线程的COM模式一旦设置就无法修改,因此触发了
Cannot change thread mode after it is set的运行时错误 - PyCharm运行时不会提前设置COM线程模式,winrt可以正常完成初始化,因此不会出现报错
解决方法
以下三种方案任选其一即可:
方案一:打包时添加窗口程序参数
打包时添加-w或--windowed参数生成无控制台的窗口程序,这类程序默认会初始化STA线程模式,和winrt的要求匹配,打包命令示例:pyinstaller -F -w notification.py其中
-F表示打包为单EXE文件,可根据自身需求调整参数。方案二:代码开头手动设置COM线程模式
在所有导入语句的最开头,先手动将COM线程模式设置为STA,之后再导入winrt相关模块:import pythoncom pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED) # 后续再导入winrt相关模块 import winrt.windows.ui.notifications as notifications import winrt.windows.data.xml.dom as dom如果运行提示找不到pythoncom,先执行
pip install pywin32安装依赖即可。方案三:将winrt逻辑放到独立线程运行
新建独立线程执行所有winrt相关逻辑,新线程默认没有设置COM模式,winrt导入时可正常完成初始化:import threading def toast_logic(): # 所有winrt相关导入和逻辑都放到这个函数内 import winrt.windows.ui.notifications as notifications import winrt.windows.data.xml.dom as dom # 此处编写你的通知业务代码 if __name__ == "__main__": t = threading.Thread(target=toast_logic) t.start() t.join()
内容的提问来源于stack exchange,提问作者rugdog
相关产品推荐
相关产品推荐

