当前位置: 首页 > news >正文

python制作的软件工具安装包

思考:

  • 如何将制作的软件工具分发给用户?
  • 打成压缩包分发给用户;
  • 制作安装程序
  • 本文介绍了一种将软件工具打包为独立安装程序的方法。核心思路是将目录文件转换为Base64编码的JSON文件,再通过解码程序还原为可执行文件。

内容说明

主要包含两个Python脚本:directory_to_base64.py将指定目录转换为包含文件内容的JSON文件;base64_to_directory.py则执行反向操作,将JSON还原为目录结构。文章详细说明了使用PyInstaller打包时的注意事项,包括资源文件路径处理、版本信息配置等,并提供了完整的示例代码和spec文件配置模板。这种方法适用于需要将多个文件打包为单一可执行安装程序的场景。

核心代码

'''directory_to_base64.py'''import os
import base64
import json
import argparse
from pathlib import Pathdef file_to_base64(file_path):"""将文件内容转换为 Base64 编码"""try:with open(file_path, 'rb') as file:content = file.read()return base64.b64encode(content).decode('utf-8')except Exception as e:print(f"Error reading file {file_path}: {e}")return Nonedef directory_to_dict(dir_path):"""递归将目录结构转换为字典"""result = {}for item in os.listdir(dir_path):item_path = os.path.join(dir_path, item)if os.path.isfile(item_path):base64_content = file_to_base64(item_path)if base64_content is not None:result[item] = {'type': 'file','content': base64_content}elif os.path.isdir(item_path):result[item] = {'type': 'directory','content': directory_to_dict(item_path)}return resultdef main():parser = argparse.ArgumentParser(description='Convert a directory and its contents to Base64 encoded JSON')parser.add_argument('--input', '-i', required=True, help='Input directory path')parser.add_argument('--output', '-o', required=True, help='Output JSON file path')args = parser.parse_args()input_dir = args.inputoutput_file = args.outputif not os.path.isdir(input_dir):print(f"Error: Input directory '{input_dir}' does not exist or is not a directory.")returntry:# 创建输出文件的目录(如果不存在)output_dir = os.path.dirname(output_file)if output_dir:os.makedirs(output_dir, exist_ok=True)# 转换目录结构为字典dir_dict = directory_to_dict(input_dir)# 添加元数据metadata = {'root_directory': os.path.basename(os.path.abspath(input_dir)),'total_files': sum(1 for _ in Path(input_dir).rglob('*') if os.path.isfile(_)),'total_directories': sum(1 for _ in Path(input_dir).rglob('*') if os.path.isdir(_))}result = {'metadata': metadata,'content': dir_dict}# 写入 JSON 文件with open(output_file, 'w') as f:json.dump(result, f, indent=2)print(f"Successfully converted directory '{input_dir}' to Base64 encoded JSON in '{output_file}'.")except Exception as e:print(f"An error occurred: {e}")if __name__ == "__main__":main()    

'''base64_to_directory.py'''import os
import base64
import json
import argparse
import sys
import pyexpatfrom pyexpat.errors import messagesdef decode_base64_to_file(base64_content, output_path):"""将 Base64 编码内容写入文件"""try:with open(output_path, 'wb') as file:file.write(base64.b64decode(base64_content))return Trueexcept Exception as e:print(f"Error writing file {output_path}: {e}")return Falsedef process_directory(content_dict, output_dir):"""递归处理目录结构并还原文件"""for item_name, item_data in content_dict.items():item_path = os.path.join(output_dir, item_name)if item_data['type'] == 'file':# 创建文件base64_content = item_data['content']if decode_base64_to_file(base64_content, item_path):print(f"Created file: {item_path}")elif item_data['type'] == 'directory':# 创建目录os.makedirs(item_path, exist_ok=True)print(f"Created directory: {item_path}")# 递归处理子目录process_directory(item_data['content'], item_path)def resource_path(relative_path):"""获取资源的绝对路径,适应打包后的环境"""if hasattr(sys, '_MEIPASS'):# 打包后的环境return os.path.join(sys._MEIPASS, relative_path)# 开发环境return os.path.join(os.path.abspath("."), relative_path)def main():"""    parser = argparse.ArgumentParser(description='Decode a Base64 encoded JSON file back to directory structure')parser.add_argument('--input', '-i', required=True, help='Input JSON file path')parser.add_argument('--output', '-o', required=True, help='Output directory path')args = parser.parse_args()"""# 使用示例input_file = resource_path("input.json")output_dir = "./Tool""""if not os.path.isfile(input_file):print(f"Error: Input file '{input_file}' does not exist or is not a file.")return
"""try:# 读取 JSON 文件with open(input_file, 'r') as f:data = json.load(f)# 创建输出目录(如果不存在)os.makedirs(output_dir, exist_ok=True)# 获取元数据metadata = data.get('metadata', {})root_directory = metadata.get('root_directory', '')total_files = metadata.get('total_files', 0)total_dirs = metadata.get('total_directories', 0)print(f"Decoding directory: {root_directory}")print(f"Total files expected: {total_files}")print(f"Total directories expected: {total_dirs}")print(f"Output location: {output_dir}")print("Starting decoding process...")# 处理内容content_dict = data.get('content', {})process_directory(content_dict, output_dir)print("Decoding completed successfully!")except Exception as e:print(f"An error occurred: {e}")if __name__ == "__main__":main()

#base64_to_directory.spec# -*- mode: python ; coding: utf-8 -*-a = Analysis(['D:\\workSpace\\python_work\\learn\\STtest\\build\\base64_to_directory.py'],pathex=[],binaries=[],datas=[('input.json', '.')],hiddenimports=[],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],noarchive=False,optimize=0,
)
pyz = PYZ(a.pure)exe = EXE(pyz,a.scripts,a.binaries,a.datas,[],name='csvfileBatchGenerationToolInstall',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=True,disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,version='version.txt'     # 指定版本信息文件
)
# version.txt
# 版本信息文件
VSVersionInfo(ffi=FixedFileInfo(filevers=(1, 0, 0, 0),prodvers=(1, 0, 0, 0),mask=0x3f,flags=0x0,OS=0x40004,fileType=0x1,subtype=0x0,date=(0, 0)),kids=[StringFileInfo([StringTable('080404B0',[StringStruct('CompanyName', ''),StringStruct('FileDescription','工具安装程序'),StringStruct('FileVersion', '1.0.0'),StringStruct('InternalName', 'csv_data_install'),StringStruct('LegalCopyright', '© 2025 Company. All rights reserved.'),StringStruct('OriginalFilename', 'install.exe'),StringStruct('ProductName', 'ToolInstall'),StringStruct('ProductVersion', '1.0.0')])]),VarFileInfo([VarStruct('Translation', [2052, 1200])  # 2052=中文])]
)

注意事项

input.json文件作为数据资源文件,需要通过os.path.join(sys._MEIPASS, relative_path)设定打包后的路径。datas=[('input.json', '.')]指定资源文件(‘原路径’,‘目标路径’)。执行命令pyinstaller "spec文件路径"打包。

http://www.lryc.cn/news/606259.html

相关文章:

  • XL2422 无线收发芯片,可用于遥控玩具和智能家居等应用领域
  • 5G-A技术浪潮勾勒通信产业新局,微美全息加快以“5.5G+ AI”新势能深化场景应用
  • 贝锐蒲公英X4 Pro 5G新品路由器:异地组网+8网口+双频WiFi全都有
  • 5G毫米波射频前端设计:从GaN功放到混合信号集成方案
  • arm架构系统打包qt程序--麒麟操作系统为例
  • [GESP202506 五级] 奖品兑换
  • Python列表完全指南:从基础到实战(2025版)
  • 八股训练--Spring
  • C#反射的概念与实战
  • 网络编程-IP
  • TCP窗口缩放配置在云服务器高延迟网络中的参数调整测试
  • Android端RTMP低延迟播放器在工业与智能场景下的架构与落地
  • 抓大鹅小游戏微信抖音流量主小程序开源
  • TGD第九篇:三维应用——视频边缘检测
  • 【AI论文】MUR:面向大型语言模型的动量不确定性引导推理
  • cuda编程笔记(11)--学习cuBLAS的简单使用
  • Coze Studio概览(四)--Prompt 管理功能详细分析
  • 分布式锁的基本原理和基于lua脚本的实现(Redisson)
  • 红黑树×协程×内存序:2025 C++后端核心三体问题攻防手册
  • 旅游城市数量最大化 01背包问题
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘plotly’问题
  • Mac安装Navicat教程Navicat Premium for Mac v17.1.9 Mac安装navicat【亲测】
  • IK 字段级别词典的升级之路
  • 【RH134 问答题】第 11 章 管理网络安全
  • ACL 2024 大模型方向优秀论文:洞察NLP前沿​关键突破!
  • 前端框架Vue3(四)——组件通信及其他API
  • SecurityContextHolder 管理安全上下文的核心组件详解
  • python之使用ffmpeg下载直播推流视频rtmp、m3u8协议实时获取时间进度
  • 金融分类提示词演示
  • 代码随想录Day35:动态规划(背包问题 二维 一维、分割等和子集)