使用PyInstaller打包Python脚本为EXE时出现'Cannot copy tree Y'错误
问题分析
报错Cannot copy tree 'Y': not a directory的核心原因:
- OneFile模式资源路径逻辑错误:使用
--onefile参数时,PyInstaller会将所有打包资源解压到系统临时目录,而非exe所在目录。代码中直接使用相对路径"Y"查找目录,自然无法定位到正确位置。 - application_path获取错误:OneFile模式下,
sys.executable指向临时目录内的临时执行文件,并非用户实际运行的exe路径,导致后续路径拼接全部失效。
解决方案
1. 调整PyInstaller打包命令
简化并修正--add-data的目标路径格式(Windows环境用;分隔源与目标路径),移除不必要的参数(如--paths及PyInstaller可自动识别的--hidden-import):
pyinstaller --onefile --windowed --icon "X/logo.ico" ^ --name "H" ^ --add-data "X/Y;Y" ^ --add-data "X/dmode.png;." ^ --add-data "X/lu.png;." ^ --add-data "X/toggle.png;." ^ --add-data "X/white.png;." ^ --hidden-import "win32gui" ^ "X/main.py"
注意:
--add-data "X/Y;Y"的目标路径不要加末尾斜杠,保持与源目录一致的层级结构。
2. 修正代码中的路径获取逻辑
OneFile模式下需通过sys._MEIPASS获取PyInstaller的临时资源解压目录,同时正确定位exe实际所在路径:
from os.path import join, exists from distutils.dir_util import copy_tree import sys import os if getattr(sys, 'frozen', False): # 获取OneFile模式下的临时资源解压目录 resource_path = sys._MEIPASS # 获取用户实际运行的exe所在目录 application_path = os.path.dirname(os.path.abspath(sys.executable)) elif __file__: resource_path = os.path.dirname(__file__) application_path = resource_path target_z_dir = join(application_path, "Z") if not exists(target_z_dir): copy_tree(join(resource_path, "Y"), target_z_dir)
关键说明
sys._MEIPASS是PyInstaller专为OneFile模式设置的环境变量,唯一指向资源解压后的临时目录,这里才能找到打包进去的Y目录。- 调整后的
application_path确保Z目录创建在用户预期的exe所在位置,而非临时目录。
内容的提问来源于stack exchange,提问作者The Amateur Coder
相关产品推荐
相关产品推荐

