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

用PyInstaller构建动态脚本执行器:嵌入式Python解释器与模块打包 - 简明教程

技术场景:

需分发的Python工具要求终端用户可动态修改执行逻辑将Python环境与指定库(如NumPy/Pandas)嵌入可执行文件实现"一次打包,动态扩展"的轻量化解决方案。

▌ 架构设计原理

1. 双模运行时识别

# 核心判断逻辑(适配开发模式与编译模式)  
def get_runtime_path():  if getattr(sys, 'frozen', False):  return os.path.dirname(sys.executable)   # 编译模式取执行文件路径  return os.path.dirname(__file__)             # 开发模式取脚本路径  

设计优势:

  • 开发阶段与发布版本使用同一套代码
  • 避免硬编码路径引发的跨平台兼容问题

2. 动态脚本加载机制

def load_script(script_name):  target_path = os.path.join(get_runtime_path(),  script_name)  if os.path.exists(target_path):   with open(target_path, 'r', encoding='utf-8') as f:  exec(f.read(),  globals())  # 在全局命名空间执行脚本  

3. 架构图

在这里插入图片描述

▌ 基础功能实现

1. 编写main.py和Run.py文件(名称随意)

main.py

import os
import sys# === 预先导入之后可能会用到的模块 ===
import numpy
import pandas# 核心判断逻辑(适配开发模式与编译模式)  
def get_runtime_path():  if getattr(sys, 'frozen', False):  return os.path.dirname(sys.executable)   # 编译模式取执行文件路径  return os.path.dirname(__file__)             # 开发模式取脚本路径# 这里一定要定义一个main函数
def main():# 导入一个可以被修改的脚本代码“Run.py”,后续可以通过它指定要被运行的脚本current_path = get_runtime_path()ScriptPath = os.path.join(current_path, "Run.py")if os.path.isfile(ScriptPath):with open(ScriptPath, 'r', encoding='utf-8') as file:exec(file.read(),globals())# 程序入口
if __name__ == "__main__":main()

Run.py

import os
import sys# 核心判断逻辑(适配开发模式与编译模式)  
def get_runtime_path():  if getattr(sys, 'frozen', False):  return os.path.dirname(sys.executable)   # 编译模式取执行文件路径  return os.path.dirname(__file__)             # 开发模式取脚本路径def load_script(script_name):  target_path = os.path.join(get_runtime_path(),  script_name)  if os.path.exists(target_path):   with open(target_path, 'r', encoding='utf-8') as f:  exec(f.read(),  globals())  # 在全局命名空间执行脚本  # def main():script_name = "example_1.py"
load_script(script_name)script_name = "example_2.py"
load_script(script_name)# if __name__ == "__main__":
#     main()

由于实际运行时上方代码Run.py由main.exe调用,将直接和main.exe共用全局命名空间中的os和sys库,因此

2. 编译 main.py

pyinstaller --onedir main.py

若没有安装pyinstaller,请先使用pip安装:

pip install pyinstaller

编译完的文件如下:

your_project_folder/
│
├──── build/ → 没有用,可以删除
├──── dist/ → 打包后的程序文件夹
│        └─── main/
│            ├─── _internal/ → 需要用到的库文件会被放在这里
│            └─── main.exe → 打包后的可执行程序
│
└──── main.spec → 打包配置文件,可以修改它来定制打包过程
_internal/ 和 main.exe → 可以一起拿出来放在其它位置(需放在同一路径下)

_internal/ 和 main.exe需在同一路径下
_internal/中将包含被引用的numpy和pandas库


3. 测试运行效果

运行 main.exe

test_main.bat

.\main.exe
pause

运行 test_main.bat 文件,查看效果:

D:\test>.\main.exe
This script is running as a compiled executable.
This script is running as a compiled executable.
一维数组:
[1 2 3 4 5]
一维数组加10:
[11 12 13 14 15]
一维数组乘2:
[ 2  4  6  8 10]
二维数组:
[[1 2][3 4]]
矩阵乘法结果:
[[ 7 10][15 22]]
原始DataFrame:Name  Age         City
0    Alice   24     New York
1      Bob   27  Los Angeles
2  Charlie   22      Chicago
3    David   32      Houston年龄大于25的行:Name  Age         City
1    Bob   27  Los Angeles
3  David   32      Houston按年龄升序排序后的DataFrame:Name  Age         City
2  Charlie   22      Chicago
0    Alice   24     New York
1      Bob   27  Los Angeles
3    David   32      Houston描述性统计量:Age
count   4.000000
mean   26.250000
std     4.349329
min    22.000000
25%    23.500000
50%    25.500000
75%    28.250000
max    32.000000D:\test>pause
请按任意键继续. . .

▌ 例程(附)

example_1.py

import numpy as np# 创建一个一维数组
arr1 = np.array([1, 2, 3, 4, 5])# 创建一个二维数组(矩阵)
arr2 = np.array([[1, 2], [3, 4]])# 数组加法
arr_sum = arr1 + 10# 数组乘法(元素级)
arr_prod = arr1 * 2# 矩阵乘法
mat_prod = np.dot(arr2, arr2)# 打印结果
print("一维数组:")
print(arr1)
print("一维数组加10:")
print(arr_sum)
print("一维数组乘2:")
print(arr_prod)
print("二维数组:")
print(arr2)
print("矩阵乘法结果:")
print(mat_prod)

运行结果:(example_1.py)

一维数组:
[1 2 3 4 5]
一维数组加10:
[11 12 13 14 15]
一维数组乘2:
[ 2  4  6  8 10]
二维数组:
[[1 2][3 4]]
矩阵乘法结果:
[[ 7 10][15 22]]

example_2.py

import pandas as pd# 创建一个简单的DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David'],'Age': [24, 27, 22, 32],'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']
}
df = pd.DataFrame(data)# 显示DataFrame
print("原始DataFrame:")
print(df)# 数据筛选:选择年龄大于25的行
filtered_df = df[df['Age'] > 25]
print("\n年龄大于25的行:")
print(filtered_df)# 数据排序:按年龄升序排序
sorted_df = df.sort_values(by='Age')
print("\n按年龄升序排序后的DataFrame:")
print(sorted_df)# 计算描述性统计量
stats = df.describe()
print("\n描述性统计量:")
print(stats)

运行结果:(example_2.py)

原始DataFrame:Name  Age         City
0    Alice   24     New York
1      Bob   27  Los Angeles
2  Charlie   22      Chicago
3    David   32      Houston年龄大于25的行:Name  Age         City
1    Bob   27  Los Angeles
3  David   32      Houston按年龄升序排序后的DataFrame:Name  Age         City
2  Charlie   22      Chicago
0    Alice   24     New York
1      Bob   27  Los Angeles
3    David   32      Houston描述性统计量:Age
count   4.000000
mean   26.250000
std     4.349329
min    22.000000
25%    23.500000
50%    25.500000
75%    28.250000
max    32.000000

相关文章:

用PyInstaller构建动态脚本执行器:嵌入式Python解释器与模块打包 - 简明教程

技术场景: 需分发的Python工具要求终端用户可动态修改执行逻辑将Python环境与指定库(如NumPy/Pandas)嵌入可执行文件实现"一次打包,动态扩展"的轻量化解决方案。 ▌ 架构设计原理 1. 双模运行时识别 # 核心判断逻辑…...

在做题中学习(89):螺旋矩阵

解法:模拟 思路:创建ret数组,用变量标记原矩阵的行数和列数,遍历一个元素就push_back进ret数组,每次遍历完一行或一列,相应行/列数--,进行顺时针螺旋遍历到为0即可。 细节:要有边界…...

从零搭建微服务项目Base(第5章——SpringBoot项目LogBack日志配置+Feign使用)

前言: 本章主要在原有项目上添加了日志配置,对SpringBoot默认的logback的配置进行了自定义修改,并详细阐述了xml文件配置要点(只对日志配置感兴趣的小伙伴可选择直接跳到第三节),并使用Feign代替原有RestT…...

数据结构《图》

数据结构《图论》 图的性质 一、无向图(Undirected Graph) 定义 由一组顶点(Vertex)和一组无向边(Edge)构成。 每条无向边用一条无方向的线段连接两个顶点,记为 ( (u, v) ),其中…...

【数据分析】通过个体和遗址层面的遗传相关性网络分析

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍原理应用场景加载R包数据下载函数个体层面的遗传相关性网络分析导入数据数据预处理构建遗传相关性的个体网络对个体网络Nij进行可视化评估和选择最佳模型评估和选择最佳模型最佳模型…...

在 macOS 的 ARM 架构上按住 Command (⌘) + Shift + .(点)。这将暂时显示隐藏文件和文件夹。

在 macOS 的 ARM 架构(如 M1/M2 系列的 Mac)上,设置 Finder(访达)来显示隐藏文件夹的步骤如下: 使用快捷键临时显示隐藏文件: 在Finder中按住 Command (⌘) Shift .(点&#xff…...

【产品经理】需求分析方法论+实践

阐述了需求分析的基本认知,包括需求分析的定义、原则和内容。接着,文章详细介绍了需求分析的十个步骤,从收集需求到结果评审,为产品经理提供了清晰的操作指南。 作为产品经理,需求分析是一个最基本的工作,但…...

Windows平台的小工具,功能实用!

今天给大家分享一款超实用的Windows平台监控工具,堪称“桌面小管家”,能帮你轻松掌握电脑的各种运行状态,比如网速、下载速度、内存和CPU占用率等常用参数,让你的电脑运行情况一目了然。 TrafficMonitor 网速监控悬浮窗软件 这款…...

意图识别概述

在当今的人工智能领域,意图识别技术是自然语言处理(NLP)中的一个重要分支,它使得机器能够理解人类语言背后的目的或意图。对于鸿蒙操作系统而言,掌握意图识别技术可以极大地提升用户体验,使设备能更好地响应…...

54. c++类型转换

c是强类型语言&#xff0c;它有自己的类型系统&#xff0c;隐式类型转换是在类型转换时&#xff0c;自动转换且数据不丢失&#xff0c;显示类型转换是指定转换类型&#xff1b;在c风格的类型转换中 &#xff0c;如下代码进行转换 #include <iostream>int main(int argc,…...

SAP-工单技术性关闭操作手册

文章目录 单个工单批量处理TECO和CLSD标识的区别 单个工单 事务代码CO02&#xff0c;输入工单号后回车 功能-》限制处理-》技术性完成 工单状态更改 撤销TECO操作 CO02输入工单号&#xff0c;功能-》限制处理-》撤销技术性完成 批量处理 事务代码COHV&#xff0c;点击生…...

Aseprite绘画流程案例(1)——画相机图标

原图&#xff1a; 步骤一&#xff1a;打开需要参照的图标 步骤二&#xff1a;将参照的图片拖放到右边&#xff0c;作为参考 步骤三&#xff1a;新建24x24的画布&#xff0c;背景为白色的画布 步骤四&#xff1a;点击菜单栏——视图——显示——像素网格&#xff08;如果画布已经…...

RESTful 的特点与普通 Web API 的区别

RESTful 是一种设计风格&#xff0c;而不仅仅是普通的 Web API。它遵循一些特定的原则和约束&#xff0c;使得 API 更加简洁、可扩展和易于理解。以下是 RESTful 的特点&#xff0c;以及与普通 Web API 的区别&#xff1a; RESTful 的特点 1. 资源导向 RESTful API 的核心是资…...

安装海康威视相机SDK后,catkin_make其他项目时,出现“libusb_set_option”错误的解决方法

硬件&#xff1a;雷神MIX G139H047LD 工控机 系统&#xff1a;ubuntu20.04 之前运行某项目时&#xff0c;处于正常状态。后来由于要使用海康威视工业相机&#xff08;型号&#xff1a;MV-CA013-21UC&#xff09;&#xff0c;便下载了并安装了该相机的SDK&#xff0c;之后运行…...

云计算架构学习之Ansible-playbook实战、Ansible-流程控制、Ansible-字典循环-roles角色

一、Ansible-playbook实战 1.Ansible-playbook安装软件 bash #编写yml [rootansible ansible]# cat wget.yml - hosts: backup tasks: - name: Install wget yum: name: wget state: present #检查playbook的语法 [rootansible ansible]…...

常用安全哈希算法bcrypt

文章目录 常用安全哈希算法bcrypt背景什么是哈希算法bcrypt哈希值验证在线工具编程方式 Bcrypt的原理 常用安全哈希算法bcrypt 背景 在设计一个系统的时候&#xff0c;肯定都有会有用户身份认证的问题&#xff0c;一般对用户校验的时候&#xff0c;都是对用户存在数据库总的密…...

Docker 常用命令基础详解(一)

一、Docker 初相识 在当今数字化时代&#xff0c;软件开发和部署的效率与灵活性成为了关键因素。Docker&#xff0c;作为一款开源的应用容器引擎&#xff0c;犹如一颗璀璨的明星&#xff0c;照亮了软件开发与部署的道路&#xff0c;为开发者们带来了前所未有的便利。它就像是一…...

网络工程师 (47)QOS

一、概念与原理 QOS即服务质量&#xff08;Quality of Service&#xff09;是一种网络技术&#xff0c;用于管理和保证网络中不同类型的质量和性能。它通过设置优先级和带宽限制等策略&#xff0c;确保关键应用&#xff08;如视频会议、语音通信&#xff09;的数据包能够在网络…...

glob 用法技巧

目录 处理大量文件节省内存 匹配多个文件扩展名 遍历多种格式文件 遍历某一个文件&#xff1a; 查找当前目录和子目录 6. 排除特定文件 7. 大小写不敏感匹配 8. 获取绝对路径 9. 处理特殊字符 处理大量文件节省内存 技巧&#xff1a;用 iglob 替代 glob&#xff0c;逐…...

Vue3 前端路由配置 + .NET8 后端静态文件服务优化策略

目录 一、Vue 前端配置&#xff08;核心&#xff09; 1. 配置 Vue Router 的 base 路径 2. 配置 Vue 的 publicPath 二、.NET 后端配置&#xff08;关键&#xff09; 1. 启用默认文档中间件 2. 配置静态文件服务的默认文档 三、验证访问路径 四、原理解释 五、常见问题…...

风铃摇晃的弧度与不安等长

晴&#xff0c;2025年2月19日 的确是&#xff0c;有依靠又有谁会去自己打伞。是啊&#xff0c;有时候生活推着我们走的样子确实挺无力的。不过谁都愿意携手走的&#xff0c;希望有一天再也不用“抛头露面”了吧。 又下载回了 X &#xff0c;马上 Gork 3 可以使用&#xff0c…...

Linux部署DeepSeek r1 模型训练

之前写过一篇windows下部署deepseekR1的文章&#xff0c;有小伙伴反馈提供一篇linux下部署DeepSeek r1 模型训练教程&#xff0c;在 Linux 环境下&#xff0c;我找了足够的相关资料&#xff0c;花费了一些时间&#xff0c;我成功部署了 DeepSeek R1 模型训练任务&#xff0c;结…...

JetBrains 2024开发者生态报告 -你尝试过用VR头戴设备编程吗

JetBrains 2024开发者生态报告&#xff1a;核心洞察 方法论 覆盖 171 个国家/地区 的 23,262 名开发者 。数据按区域开发者数量和就业状态加权。 主要趋势 AI 整合 80% 的公司允许使用第三方 AI 工具&#xff08;如 ChatGPT、Copilot&#xff09;。18% 的开发者将 AI 集成到产…...

Spring Boot “约定大于配置”

什么是“约定大于配置”&#xff1f; “约定大于配置”是一种简化开发的设计理念。简单来说&#xff0c;就是框架默认提供了常见的配置和行为&#xff0c;开发者只需要按照约定来编写代码&#xff0c;避免了繁琐的配置&#xff0c;只在需要时进行定制和调整。这种理念在Spring…...

【大语言模型_3】ollama本地加载deepseek模型后回答混乱问题解决

背景&#xff1a; 本地下载了DeepSeek-R1-Distill-Qwen-7B模型后&#xff0c;通过ollama create DeepSeek-R1-Distill-Qwen-7B -f ds7b.mf加载模型启动后回答混乱&#xff0c;无法使用。 解决方法 重新下载模型&#xff0c;选择了DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf 重…...

汇能感知的光谱相机/模块产品有哪些?

CM020A 分辨率&#xff1a;1600H1200V 光谱范围&#xff1a;350~950nm 光谱分辨率&#xff1a;1nm 接口&#xff1a;USB2.0 帧率&#xff1a;16001200 (6帧) 输出格式&#xff1a;Raw 8bit FOV&#xff1a;D73.5H58.8V44.1 相机尺寸&#xff1a;505055mm VM02S10 分辨率…...

Spring中Bean的四种实例化方法

Bean的四种实例化方法 Bean是Spring核心的概念&#xff0c;另外一个核心的概念是AOP。官网上&#xff0c;Bean的解释是&#xff1a; In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans…...

Office word打开加载比较慢处理方法

1.添加safe参数 ,找到word启动项,右击word,选择属性 , 添加/safe , 应用并确定 2.取消加载项,点击文件,点击选项 ,点击加载项,点击转到,取消所有勾选,确定。...

一台服务器将docker image打包去另一天服务器安装这个镜像

一台服务器将docker image打到去另一天服务器安装这个镜像 1. 打包2.另一台服务器执行 1. 打包 docker save -o nebula-graph-studio.tar harbor1.vm.example.lan/dockerio/vesoft/nebula-graph-studioxxx.tar 是打包好的文件 后面的是 docker image 2.另一台服务器执行 docke…...

在局域网中连接Grafana数据源

目录 登录Grafana 添加数据源 配置数据源 保存并测试 使用数据源 注意事项 登录Grafana 打开浏览器&#xff0c;访问Grafana的地址&#xff0c;默认是http://localhost:3000。 使用默认用户名和密码登录&#xff08;通常是admin/admin&#xff09;&#xff0c;登录后建议…...