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

统信系统小程序(四)linux环境下的python程序打包Nuitka工具

一有前辈写了win环境的Nuitka打包工具觉得很好用。打包的效果很小大小只有几百K。linux环境下测试Nuitka没有那么惊艳打包时间很长估计1小时。打包效果也不好一半都要几十M。不知道问题出在哪但是暂时能用当然里边也包括了pyinstaller功能。运行需要什么库就装什么。例如pip install nuitka。二程序或打包时引入的 Python 库有时无视现有会话总线强制调用linux已废弃的 dbus-launch 命令。现代 Linux 桌面含 UOS已全面采用 systemd 管理 D-BusUOS 20 默认使用 dbus-broker不再预装 dbus-launch因此直接报 EOF。是否在打包命令中添加--exclude-module dbus --exclude-module dbus.mainloop若实际未用到以下是代码import tkinter as tk from tkinter import ttk, filedialog, messagebox import subprocess import os import sys import threading def get_resource_path(relative_path): 获取资源文件的绝对路径兼容打包前后的情况 try: # PyInstaller创建的临时文件夹 base_path sys._MEIPASS except Exception: base_path os.path.abspath(.) return os.path.join(base_path, relative_path) class PyToLinuxEXE: def __init__(self): self.root tk.Tk() self.root.title(Python程序打包工具) self.root.geometry(800x600) # 设置背景色为淡黄色 self.bg_color #FFFACD # 淡黄色 self.root.configure(bgself.bg_color) self.source_file tk.StringVar() self.output_dir tk.StringVar() self.output_name tk.StringVar() self.one_file tk.BooleanVar(valueTrue) self.console tk.BooleanVar(valueFalse) self.icon_file tk.StringVar() self.packaging_tool tk.StringVar(valuepyinstaller) # 默认打包工具 # 设置默认字体 self.default_font (fangsong ti, 12) # 设置全局字体 self.set_global_font() # 设置糖果色 self.candy_colors { button_bg: #FFB6C1, # 粉红色 button_fg: #8B008B, # 深洋红色 button_active_bg: #FF69B4, # 热粉红色 browse_button_bg: #98FB98, # 淡绿色 browse_button_fg: #006400, # 深绿色 browse_button_active_bg: #00FF7F, # 春绿色 action_button_bg: #87CEFA, # 淡蓝色 action_button_fg: #000080, # 海军蓝 action_button_active_bg: #4169E1 # 皇家蓝 } # 设置输出默认值 self.output_dir.set(os.path.expanduser(~/test/xuanzhuan)) # 设置源文件默认值如果文件存在 default_source /home/huanghe/PycharmProjects/pythonEMY if os.path.exists(default_source): self.source_file.set(default_source) # 自动设置输出文件名 self.output_name.set(os.path.splitext(os.path.basename(default_source))[0]) # 设置图标文件默认值如果文件存在 default_icon /home/huanghe/test/file.ico if os.path.exists(default_icon): self.icon_file.set(default_icon) self.create_widgets() def set_global_font(self): # 设置默认字体 self.default_font (fangsong ti, 12) # 配置根窗口的默认字体 self.root.option_add(*Font, self.default_font) # 创建自定义样式 style ttk.Style() style.configure(., fontself.default_font, backgroundself.bg_color) style.configure(TButton, fontself.default_font) style.configure(TLabel, fontself.default_font, backgroundself.bg_color) style.configure(TCheckbutton, fontself.default_font, backgroundself.bg_color) style.configure(TEntry, fontself.default_font) style.configure(TFrame, backgroundself.bg_color) def create_widgets(self): main_frame tk.Frame(self.root, bgself.bg_color) main_frame.pack(filltk.BOTH, expandTrue, padx5, pady5) # 控制区域 control_frame tk.Frame(main_frame, bgself.bg_color) control_frame.pack(filltk.X, pady3) # 源文件选择 input_frame tk.Frame(control_frame, bgself.bg_color) input_frame.pack(filltk.X, pady2) tk.Label(input_frame, text源文件:, width10, anchortk.W, fontself.default_font, bgself.bg_color).pack( sidetk.LEFT) tk.Entry(input_frame, textvariableself.source_file, fontself.default_font, bgwhite).pack(sidetk.LEFT, filltk.X, expandTrue, padx3) tk.Button(input_frame, text浏览, commandself.browse_source, width8, bgself.candy_colors[browse_button_bg], fgself.candy_colors[browse_button_fg], activebackgroundself.candy_colors[browse_button_active_bg], fontself.default_font, relieftk.RAISED, bd2).pack(sidetk.LEFT, padx3) # 输出目录选择 output_frame tk.Frame(control_frame, bgself.bg_color) output_frame.pack(filltk.X, pady2) tk.Label(output_frame, text输出目录:, width10, anchortk.W, fontself.default_font, bgself.bg_color).pack( sidetk.LEFT) tk.Entry(output_frame, textvariableself.output_dir, fontself.default_font, bgwhite).pack(sidetk.LEFT, filltk.X, expandTrue, padx3) tk.Button(output_frame, text浏览, commandself.browse_output, width8, bgself.candy_colors[browse_button_bg], fgself.candy_colors[browse_button_fg], activebackgroundself.candy_colors[browse_button_active_bg], fontself.default_font, relieftk.RAISED, bd2).pack(sidetk.LEFT, padx3) # 输出文件名 name_frame tk.Frame(control_frame, bgself.bg_color) name_frame.pack(filltk.X, pady2) tk.Label(name_frame, text输出名称:, width10, anchortk.W, fontself.default_font, bgself.bg_color).pack( sidetk.LEFT) tk.Entry(name_frame, textvariableself.output_name, fontself.default_font, bgwhite).pack(sidetk.LEFT, filltk.X, expandTrue, padx3) # 打包工具选择 tool_frame tk.Frame(control_frame, bgself.bg_color) tool_frame.pack(filltk.X, pady2) tk.Label(tool_frame, text打包工具:, width10, anchortk.W, fontself.default_font, bgself.bg_color).pack( sidetk.LEFT) tool_combo ttk.Combobox(tool_frame, textvariableself.packaging_tool, values[pyinstaller, cx_freeze, nuitka, briefcase], statereadonly, fontself.default_font, width15) tool_combo.pack(sidetk.LEFT, padx3) tool_combo.set(nuitka) # 设置默认值 # 选项区域 options_frame tk.Frame(control_frame, bgself.bg_color) options_frame.pack(filltk.X, pady10) tk.Label(options_frame, text打包选项:, width10, anchortk.W, fontself.default_font, bgself.bg_color).pack( sidetk.LEFT) options_container tk.Frame(options_frame, bgself.bg_color) options_container.pack(sidetk.LEFT, filltk.X, expandTrue) tk.Checkbutton(options_container, text生成单个文件, variableself.one_file, fontself.default_font, bgself.bg_color, selectcolorwhite).pack( sidetk.LEFT, padx10) tk.Checkbutton(options_container, text无控制台窗口, variableself.console, fontself.default_font, bgself.bg_color, selectcolorwhite).pack( sidetk.LEFT, padx10) # 图标文件选择 icon_frame tk.Frame(control_frame, bgself.bg_color) icon_frame.pack(filltk.X, pady2) tk.Label(icon_frame, text图标文件:, width10, anchortk.W, fontself.default_font, bgself.bg_color).pack( sidetk.LEFT) tk.Entry(icon_frame, textvariableself.icon_file, fontself.default_font, bgwhite).pack(sidetk.LEFT, filltk.X, expandTrue, padx3) tk.Button(icon_frame, text浏览, commandself.browse_icon, width8, bgself.candy_colors[browse_button_bg], fgself.candy_colors[browse_button_fg], activebackgroundself.candy_colors[browse_button_active_bg], fontself.default_font, relieftk.RAISED, bd2).pack(sidetk.LEFT, padx3) # 按钮区域 button_frame tk.Frame(control_frame, bgself.bg_color) button_frame.pack(filltk.X, pady10) self.pack_button tk.Button(button_frame, text开始打包, commandself.start_packaging, bgself.candy_colors[action_button_bg], fgself.candy_colors[action_button_fg], activebackgroundself.candy_colors[action_button_active_bg], fontself.default_font, relieftk.RAISED, bd2) self.pack_button.pack(sidetk.RIGHT, padx5) tk.Button(button_frame, text退出, commandself.root.quit, bgself.candy_colors[button_bg], fgself.candy_colors[button_fg], activebackgroundself.candy_colors[button_active_bg], fontself.default_font, relieftk.RAISED, bd2).pack(sidetk.RIGHT, padx5) # 内容区域 content_frame tk.Frame(main_frame, bgself.bg_color) content_frame.pack(filltk.BOTH, expandTrue, pady5) # 日志区域 log_container tk.Frame(content_frame, bgself.bg_color) log_container.pack(filltk.BOTH, expandTrue, padx2) tk.Label(log_container, text打包日志, fontself.default_font, bgself.bg_color).pack(anchortk.W) log_frame tk.Frame(log_container, bgself.bg_color) log_frame.pack(filltk.BOTH, expandTrue) self.log_text tk.Text(log_frame, height20, fontself.default_font, bgwhite) scrollbar tk.Scrollbar(log_frame, commandself.log_text.yview) self.log_text.configure(yscrollcommandscrollbar.set) self.log_text.pack(sidetk.LEFT, filltk.BOTH, expandTrue) scrollbar.pack(sidetk.RIGHT, filltk.Y) # 进度条 self.progress ttk.Progressbar(main_frame, modeindeterminate) self.progress.pack(filltk.X, padx5, pady5) def browse_source(self): filename filedialog.askopenfilename( title选择Python文件, filetypes[(Python files, *.py), (All files, *.*)] ) if filename: self.source_file.set(filename) # 自动设置输出文件名 if not self.output_name.get(): self.output_name.set(os.path.splitext(os.path.basename(filename))[0]) def browse_output(self): directory filedialog.askdirectory( title选择输出目录 ) if directory: self.output_dir.set(directory) def browse_icon(self): filename filedialog.askopenfilename( title选择图标文件, filetypes[(Icon files, *.ico *.png), (All files, *.*)] ) if filename: self.icon_file.set(filename) def log_message(self, message): self.log_text.insert(tk.END, message \n) self.log_text.see(tk.END) self.root.update_idletasks() def start_packaging(self): # 在后台线程中执行打包操作 thread threading.Thread(targetself.package_executable) thread.daemon True thread.start() def package_executable(self): # 禁用打包按钮并开始进度条 self.pack_button.config(statetk.DISABLED) self.progress.start() try: # 检查输入 source_file self.source_file.get() if not source_file: messagebox.showwarning(警告, 请选择源文件) return if not os.path.exists(source_file): messagebox.showwarning(警告, 源文件不存在) return output_dir self.output_dir.get() if not output_dir: messagebox.showwarning(警告, 请选择输出目录) return if not os.path.exists(output_dir): os.makedirs(output_dir) output_name self.output_name.get() if not output_name: output_name os.path.splitext(os.path.basename(source_file))[0] # 获取选择的打包工具 tool self.packaging_tool.get() # 根据选择的工具构建命令 if tool pyinstaller: cmd self.build_pyinstaller_command(source_file, output_dir, output_name) elif tool cx_freeze: cmd self.build_cx_freeze_command(source_file, output_dir, output_name) elif tool nuitka: cmd self.build_nuitka_command(source_file, output_dir, output_name) elif tool briefcase: cmd self.build_briefcase_command(source_file, output_dir, output_name) else: messagebox.showerror(错误, f不支持的打包工具: {tool}) return self.log_message(f使用工具: {tool}) self.log_message(执行命令: .join(cmd)) self.log_message(开始打包...) # 执行命令 process subprocess.Popen( cmd, stdoutsubprocess.PIPE, stderrsubprocess.STDOUT, universal_newlinesTrue, cwdos.path.dirname(source_file) if os.path.isfile(source_file) else os.getcwd() ) # 实时显示输出 for line in process.stdout: self.log_message(line.strip()) process.wait() if process.returncode 0: self.log_message(打包完成!) messagebox.showinfo(成功, 可执行文件已生成) else: self.log_message(打包失败!) messagebox.showerror(错误, 打包过程中出现错误) except Exception as e: self.log_message(f发生错误: {str(e)}) messagebox.showerror(错误, f发生错误: {str(e)}) finally: # 重新启用打包按钮并停止进度条 self.progress.stop() self.pack_button.config(statetk.NORMAL) def build_pyinstaller_command(self, source_file, output_dir, output_name): 构建PyInstaller命令 cmd [sys.executable, -m, PyInstaller] # 添加选项 if self.one_file.get(): cmd.append(--onefile) if self.console.get(): cmd.append(--noconsole) else: cmd.append(--console) if self.icon_file.get(): icon_file self.icon_file.get() if os.path.exists(icon_file): cmd.extend([--icon, icon_file]) # 设置输出目录 cmd.extend([--distpath, output_dir]) cmd.extend([--workpath, os.path.join(output_dir, build)]) cmd.extend([--specpath, output_dir]) # 添加源文件 cmd.append(source_file) return cmd def build_cx_freeze_command(self, source_file, output_dir, output_name): 构建cx_Freeze命令 cmd [sys.executable, -m, cx_Freeze, source_file] # 添加选项 cmd.extend([--target-dir, output_dir]) if self.icon_file.get(): icon_file self.icon_file.get() if os.path.exists(icon_file): cmd.extend([--icon, icon_file]) return cmd def build_nuitka_command(self, source_file, output_dir, output_name): 构建Nuitka命令 - 针对取证单程序优化版 cmd [sys.executable, -m, nuitka, --standalone, --enable-plugintk-inter] # 添加选项 cmd.extend([--output-dir output_dir]) if self.one_file.get(): cmd.append(--onefile) # 解决Anaconda环境问题 cmd.append(--static-libpythonno) # 优化和清理选项 cmd.append(--remove-output) cmd.append(--jobs4) cmd.append(--clean-cacheall) # 处理matplotlib警告 cmd.append(--enable-pluginno-qt) # 排除D-Bus相关模块UOS系统不需要避免dbus-launch错误 cmd.append(--nofollow-import-todbus) cmd.append(--nofollow-import-todbus.mainloop) cmd.append(--nofollow-import-togi.repository.Gio) cmd.append(--nofollow-import-togi.repository.GLib) # 如果你的程序需要特定的DLL或数据文件可以在这里添加 # 例如如果需要包含模板文件 # cmd.append(--include-data-filetemplate.xlsxtemplate.xlsx) # Linux图标处理 - 修复图标参数 if self.icon_file.get(): icon_file self.icon_file.get() if os.path.exists(icon_file): # 对于ICO文件 if icon_file.lower().endswith(.ico): cmd.extend([--windows-icon-from-ico icon_file]) elif icon_file.lower().endswith((.png, .jpg, .jpeg)): # 对于PNG/JPG文件 cmd.extend([--linux-onefile-icon icon_file]) # 添加源文件 cmd.append(source_file) return cmd def build_briefcase_command(self, source_file, output_dir, output_name): 构建Briefcase命令 # Briefcase通常需要更复杂的项目结构这里提供一个基础命令 cmd [sys.executable, -m, briefcase, create] # 设置输出目录 # 注意Briefcase的参数可能需要根据具体项目结构调整 return cmd def run(self): self.root.mainloop() if __name__ __main__: app PyToLinuxEXE() app.run()
http://www.gsyq.cn/news/1336023.html

相关文章:

  • Python图像处理避坑指南:TIF转PNG时,用GDAL还是PIL/OpenCV?看完这篇再决定
  • PyTorch实战(35)——使用PyTorch Profiler分析模型推理性能
  • 使用Python快速上手Taotoken实现你的第一个大模型对话
  • 10分钟精通:如何在VSCode中实现专业级图表实时预览?
  • 离子交换柱生产厂家哪家靠谱?水喷式真空泵厂家推荐:丰亿环保领衔,2026年国内优质水喷式真空泵与离子交换柱生产厂家盘点 - 栗子测评
  • applera1n:免费绕过iOS 15-16激活锁的终极指南
  • 混合搅拌机厂家哪家好?干法制粒机生产厂家哪家好?2026年国内靠谱厂家实力盘点与推荐:科洛伊机械领衔 - 栗子测评
  • 2026年238个好发CCF-A的强化学习idea全面汇总!
  • Phillips SDM01 0940860010091 003149电子控制单元
  • Linux GPIO框架深度解析:从用户空间到内核驱动的完整路径
  • 2026紧固件与地基构件行业发展现状:预埋钢板槽塑翼螺母灌注桩螺旋地桩厂家及晨翔紧固件产品矩阵优势分析 - 栗子测评
  • CANN/cannbot-skills 矩阵乘法 Swizzle2D 优化案例
  • parse库错误处理与异常管理:构建可靠的字符串解析应用
  • CANN/asc-devkit协作组shfl函数
  • CANN/asc-devkit asc_any函数
  • Redis——string类型相关指令
  • 避开勒让德函数那些坑:GRACE数据处理中MATLAB高效计算与调试技巧
  • 如何快速集成Android-shapeLoadingView:5分钟实现酷炫加载效果
  • 杭州学书法艺考去哪家?2026杭州书法艺考机构推荐:杭州书法统考通过率高的机构+杭州师资力量强的书法培训机构 - 栗子测评
  • Omnizart实战教程:如何快速转录你最喜欢的歌曲
  • Plexdrive vs rclone深度对比:哪个更适合你的需求?
  • 工业防爆监控技术解析:内蒙古高危场景的选型与落地方案
  • RTL优化实战:一行代码如何导致40%面积浪费与30%功耗增加
  • 在鸿蒙系统上从零构建Linux交叉编译工具链:原理、步骤与踩坑实录
  • Orbit可编程注意力功能详解:定制你的记忆体验
  • kagent MCP工具集成完全指南:从Kubernetes到Grafana的完整工具链
  • 从实验室到智能小车:霍尔传感器除了测磁场,还能怎么玩?(避坑指南)
  • 告别手动调参!用Quartus Prime的NCO核(DDS)一键生成ASK调制信号(附Verilog代码)
  • TikTok-Live-Connector多平台集成:Web应用与移动端适配方案
  • AndrOBD终极指南:如何用Android设备诊断你的爱车