解决tk打包的exe文件运行时出现的叶子图标问题

本文介绍如何使用PyInstaller将Python脚本编译成exe文件时,为程序窗口设置自定义图标。通过将图标文件编码进Python脚本并在运行时解码显示,确保编译后的程序能正确展示图标。

转载记录
https://www.cnblogs.com/d0main/p/7444837.html

问题:

使用pyinstaller将.py文件编译成.exe文件时,想要使用自己心仪的图标(.ico)比较麻烦。
在使用pyinstaller时,用参数:–i可以给生成的可执行文件设定自定义图标,但这只是给程序文件一个图标,而在程序开启后,窗口左上角的图标以及任务栏显示的却依旧是默认的tk图标(羽毛)。
在这里插入图片描述
如果想要在脚本中直接函数iconbitmap(‘图标路径’)来设定窗口左上角图标,虽然使用python编译器可以正确呈现自定义的图标,但是用pyinstaller编译成.exe文件之后,程序窗口可能组件呈现不出来或者干脆程序无法执行。
在这里插入图片描述

解决方法

准备:一个图标文件xxx.ico

图标文件同目录下首先创建一个py文件,源码如下:

import base64
with open("icon.py","w") as f:
  f.write('class Icon(object):\n')
  f.write('\tdef __init__(self):\n')
  f.write("\t\tself.img='")
with open(r"F:\ICO图标素材\xxx.ico","rb") as i:
  b64str = base64.b64encode(i.read())
  with open("icon.py","ab+") as f:
    f.write(b64str)
with open("icon.py","a") as f:
  f.write("'")

此时,在同文件夹下产生一个icon.py的模块。把它保存在类当中是为了让我们要编译的py能够创建并调用之。

可能类中的字符串长度很长很长。。。。不用在意

接下来就到我们的tk程序中调用这个类

import icon,os,base64
from icon import Icon
with open('tmp.ico','wb') as tmp:
    tmp.write(base64.b64decode(Icon().img))
root.iconbitmap('tmp.ico')
os.remove('tmp.ico')

代替脚本中类似下面这样的语句

root.iconbitmap(‘pen.ico’)

经过如上两步,就能在使用pyinstaller编译后正确的呈现自定义图标而且程序能够正常工作了。这种将文件在开发阶段编码后编译在可执行文件,到了程序运行的时候自动生成的方法也能够用到产生程序其他必要的文件中。

<think>我们之前打包使用了--console参数,这样在运行exe会显示控制台窗口。如果程序启动过程中发生错误导致崩溃,控制台窗口会快速关闭,难以捕捉错误信息。 为了解决闪退问题并快速定位错误,我们可以采取以下步骤: 1. **保留控制台窗口**:在调试阶段,我们可以暂保留控制台窗口,这样程序崩溃错误信息会停留在控制台。但用户要求不显示控制台,所以调试完成后需要去掉。 2. **添加错误日志**:在代码中捕获异常并写入日志文件,这样即使控制台关闭,我们也能查看日志。 3. **使用try-except捕获异常**:在程序入口处添加全局异常捕获。 4. **优化打包脚本**:在打包,我们可以先保留控制台(使用--console)进行调试,确认没有错误后再改用--noconsole。 具体操作如下: ### 步骤1:修改主程序,添加全局异常捕获 在`audio_flash_tool.py`的入口部分(如果有GUI,则在GUI启动前)添加错误日志记录。 假设程序有一个主函数,例如: ```python import traceback import logging def main(): # 初始化应用等 pass if __name__ == "__main__": # 设置日志记录 logging.basicConfig(filename='AudioFlashTool.log', level=logging.ERROR, format='%(asctime)s %(levelname)s: %(message)s') try: main() except Exception as e: logging.error("Unhandled exception: %s", str(e)) logging.error(traceback.format_exc()) # 如果有GUI,可以弹窗提示 # 例如使用tkinter.messagebox.showerror("Error", str(e)) # 但注意,如果GUI还没启动,弹窗可能失败,所以直接记录日志更安全 raise # 为了在控制台也能看到,调试保留 ``` 这样,程序崩溃会将错误信息记录到当前目录下的`AudioFlashTool.log`文件中。 ### 步骤2:打包保留控制台(调试阶段) 在`build.py`中,我们使用`--console`参数打包,这样运行exe会显示控制台窗口,错误信息会打印在控制台。 当确认程序运行稳定后,再改用`--noconsole`重新打包。 ### 步骤3:测试打包后的exe 运行打包后的exe,观察控制台输出或查看日志文件,定位错误。 常见错误: - 资源文件找不到:检查`resource_path`函数是否正确,以及打包`--add-data`是否包含所有资源。 - 依赖的DLL缺失:特别是`HiAudioUploadTool.exe`和`HiAudioGetLogTool.exe`可能需要额外的DLL,确保这些DLL也被打包(如果它们在同一目录,PyInstaller会自动打包,但有需要手动添加)。 如果发现缺少文件,可以在打包脚本中通过`--add-data`添加。 ### 步骤4:最终打包 调试完成后,将`build.py`中的`--console`改为`--noconsole`,重新打包。 ### 优化后的打包脚本(调试阶段) 注意:调试阶段保留`--console`,并确保日志功能已添加。 如果问题仍然难以捕捉,可以尝试在程序启动暂停(例如在最后添加`input("Press Enter to exit...")`),但这样只适用于控制台模式。 另一种方法:即使使用`--noconsole`,我们也可以将标准输出重定向到文件(在代码中设置),但上面的日志记录方法已经覆盖。 ### 示例:修改后的打包脚本(调试用) 在`build.py`中,我们仍然使用`--console`,然后运行测试。 当程序稳定后,将`build.py`中的`--console`替换为`--noconsole`,并重新打包。 注意:最终发布版本使用`--noconsole`。 按照上述步骤,可以定位和解决闪退问题。 §§相关问题§§ 1. 如何避免PyInstaller打包后因缺失资源文件导致的程序崩溃? 2. 除了日志文件,还有哪些方法可以捕获并查看PyInstaller打包程序的崩溃信息? 3. 在最终发布版本中,如何确保程序在无控制台窗口的情况下优雅处理异常并提示用户? 4. 如何将PyInstaller打包EXE文件与依赖的外部可执行文件(如HiAudioUploadTool.exe)正确关联路径? 5. 使用PyInstaller打包,如何自动包含项目中所有依赖的资源文件(如整个目录)? </think>### 解决 EXE 闪退问题的优化方案 当打包EXE 运行控制台窗口闪退,通常是由于资源加载失败或未捕获的异常导致。以下是快速定位和解决的优化脚本: #### 1. 添加错误日志捕获机制(关键) 在 `audio_flash_tool.py` 中添加全局异常捕获: ```python import sys import os import traceback import logging def resource_path(relative_path): """ 处理资源文件路径 """ try: base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) def main(): # 原有应用初始化代码 root = tk.Tk() AudioFlashTool(root) root.mainloop() if __name__ == "__main__": # 配置错误日志 logging.basicConfig( filename='audio_tool_error.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s: %(message)s' ) try: main() except Exception as e: # 记录完整错误堆栈 error_msg = f"CRASH: {str(e)}\n{traceback.format_exc()}" logging.error(error_msg) # 显示用户友好提示 tk.messagebox.showerror( "致命错误", f"程序崩溃: {str(e)}\n详细信息查看 audio_tool_error.log" ) ``` #### 2. 优化打包脚本 `debug_build.py` ```python import PyInstaller.__main__ import os PyInstaller.__main__.run([ 'audio_flash_tool.py', '--onefile', '--console', # 调试阶段保留控制台 '--add-data=config.json;.', '--add-data=headphones.ico;.', '--add-data=devices_dir;devices_dir', '--add-data=HiAudioUploadTool.exe;.', '--add-data=HiAudioGetLogTool.exe;.', '--icon=headphones.ico', '--name=AudioFlashTool_Debug', '--clean' ]) ``` #### 3. 诊断流程 1. **生成调试版 EXE**: ```bash python debug_build.py ``` 2. **运行诊断**: - 在命令行直接运行 EXE(不要双击): ```bash dist/AudioFlashTool_Debug.exe ``` - 观察控制台输出的完整错误信息 3. **查看日志文件**: - 程序崩溃后检查生成的 `audio_tool_error.log` - 定位具体错误行和资源加载问题 #### 4. 常见问题解决方案 | 错误类型 | 解决方案 | |---------|---------| | 资源文件缺失 | 检查 `--add-data` 参数格式,确保资源路径正确 | | DLL 加载失败 | 添加 `--add-binary` 包含缺失 DLL | | 权限问题 | 以管理员身份运行 EXE | | 杀毒软件拦截 | 添加白名单或暂禁用杀毒软件 | | 路径编码错误 | 在资源路径中使用 `os.path.normpath()` 标准化路径 | #### 5. 最终发布版本 修复所有错误后,修改打包脚本: ```python # 修改为无控制台版本 params[2] = '--noconsole' # 移除调试名称后缀 params[9] = '--name=AudioFlashTool' ``` > 此方案确保:<br> > 1. 调试阶段通过控制台直接显示错误<br> > 2. 自动生成详细错误日志<br> > 3. 用户端显示友好错误提示<br> > 4. 资源加载异常精准定位
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值