用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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/70212.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

山石网科×阿里云通义灵码,开启研发“AI智造”新时代

近日,山石网科正式宣布全面接入阿里云通义灵码企业专属版,这标志着山石网科在研发智能化、自动化领域迈出重要一步,为研发工作注入强大的AI动力,实现多维度的效率飞跃。 此次合作,阿里云通义灵码依托强大的AI能力&…

《被讨厌的勇气》(六)

1.自由就是被别人讨厌。 2.毫不在意别人的评价、不害怕被别人讨厌、不追求被他人认可,如果不付出以上这些代价,那就无法贯彻自己的生活方式,也就是不能获得自由。 3.在意你的脸的只有你自己。 4.不去干涉别人的课题也不让别人干涉自己的课题.…

使用 PyTorch 实现标准卷积神经网络(CNN)

卷积神经网络(CNN)是深度学习中的重要组成部分,广泛应用于图像处理、语音识别、视频分析等任务。在这篇博客中,我们将使用 PyTorch 实现一个标准的卷积神经网络(CNN),并介绍各个部分的作用。 什…

SpringBoot2.0整合Redis(Lettuce版本)

前言: 目前java操作redis的客户端有jedis跟Lettuce。在springboot1.x系列中,其中使用的是jedis, 但是到了springboot2.x其中使用的是Lettuce。 因为我们的版本是springboot2.x系列,所以今天使用的是Lettuce。关于jedis跟lettuce的区别&#…

qt + opengl 给立方体增加阴影

在前几篇文章里面学会了通过opengl实现一个立方体,那么这篇我们来学习光照。 风氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看起来的样子: 1 环境光照(Ambient …

大模型工具大比拼:SGLang、Ollama、VLLM、LLaMA.cpp 如何选择?

简介:在人工智能飞速发展的今天,大模型已经成为推动技术革新的核心力量。无论是智能客服、内容创作,还是科研辅助、代码生成,大模型的身影无处不在。然而,面对市场上琳琅满目的工具,如何挑选最适合自己的那…

stream流常用方法

1.reduce 在Java中,可以使用Stream API的reduce方法来计算一个整数列表的乘积。reduce方法是一种累积操作,它可以将流中的元素组合起来,返回单个结果。对于计算乘积,你需要提供一个初始值(通常是1,因为乘法…

pgAdmin4在mac m1上面简单使用(Docker)

问题 想要在本地简单了解一下pgAdmin4一些简单功能。故需要在本机先安装看一看。 安装步骤 拉取docker镜像 docker pull dpage/pgadmin4直接简单运行pgAdmin4 docker run --name pgAdmin4 -p 5050:80 \-e "PGADMIN_DEFAULT_EMAILuserdomain.com" \-e "PGAD…

ubuntu下安装TFTP服务器

在 Ubuntu 系统下安装和配置 TFTP(Trivial File Transfer Protocol)服务器可以按照以下步骤进行: 1. 安装 TFTP 服务器软件包 TFTP 服务器通常使用 tftpd-hpa 软件包,你可以使用以下命令进行安装: sudo apt update …

Softing线上研讨会 | 自研还是购买——用于自动化产品的工业以太网

| 线上研讨会时间:2025年1月27日 16:00~16:30 / 23:00~23:30 基于以太网的通信在工业自动化网络中的重要性日益增加。设备制造商正面临着一大挑战——如何快速、有效且经济地将工业以太网协议集成到其产品中。其中的关键问题包括:是否只需集成单一的工…

vscode创建java web项目

一.项目部署 1.shiftctrlp,选择java项目 2.选择maven create from arcetype 3.选择webapp 4.目录结构如下,其中index.jsp是首页 5.找到左下角的servers,添加tomcat服务器 选择 再选择: 找到你下载的tomcat 的bin目录的上一级目录&#x…

C语言指针学习笔记

1. 指针的定义 指针(Pointer)是存储变量地址的变量。在C语言中,指针是一种非常重要的数据类型,通过指针可以直接访问和操作内存。 2. 指针的声明与初始化 2.1 指针声明 指针变量的声明格式为:数据类型 *指针变量名…

DeepSeek R1生成图片总结2(虽然本身是不能直接生成图片,但是可以想办法利用别的工具一起实现)

DeepSeek官网 目前阶段,DeepSeek R1是不能直接生成图片的,但可以通过优化文本后转换为SVG或HTML代码,再保存为图片。另外,Janus-Pro是DeepSeek的多模态模型,支持文生图,但需要本地部署或者使用第三方工具。…

什么是Dubbo?Dubbo框架知识点,面试题总结

本篇包含什么是Dubbo,Dubbo的实现原理,节点角色说明,调用关系说明,在实际开发的场景中应该如何选择RPC框架,Dubbo的核心架构,Dubbo的整体架构设计及分层。 主页还有其他的面试资料,有需要的可以…

kafka消费能力压测:使用官方工具

背景 在之前的业务场景中,我们发现Kafka的实际消费能力远低于预期。尽管我们使用了kafka-go组件并进行了相关测试,测试情况见《kafka-go:性能测试》这篇文章。但并未能准确找出消费能力低下的原因。 我们曾怀疑这可能是由我的电脑网络带宽问题或Kafka部…

【大学生职业规划大赛备赛PPT资料PDF | 免费共享】

自取链接: 链接:https://pan.quark.cn/s/4fa45515325e 📢 同学,你是不是正在为职业规划大赛发愁? 想展示独特思路却不知如何下手? 想用专业模板却找不到资源? 别担心!我整理了全网…

ubuntu20动态修改ip,springboot中yaml的内容的读取,修改,写入

文章目录 前言引入包yaml原始内容操作目标具体代码执行查看结果总结: 前言 之前有个需求,动态修改ubuntu20的ip,看了下: 本质上是修改01-netcfg.yaml文件,然后执行netplan apply就可以了。 所以,需求就变成了 如何对ya…

【算法】双指针(下)

目录 查找总价格为目标值的两个商品 暴力解题 双指针解题 三数之和 双指针解题(左右指针) 四数之和 双指针解题 双指针关键点 注意事项 查找总价格为目标值的两个商品 题目链接:LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode&#x…

Windows 图形显示驱动开发-IoMmu 模型

输入输出内存管理单元 (IOMMU) 是一个硬件组件,它将支持具有 DMA 功能的 I/O 总线连接到系统内存。 它将设备可见的虚拟地址映射到物理地址,使其在虚拟化中很有用。 在 WDDM 2.0 IoMmu 模型中,每个进程都有一个虚拟地址空间,即&a…

软件测评报告包括哪些内容?第三方软件测评机构推荐

在当今信息技术飞速发展的时代,软件的品质与性能直接影响到企业的运营效率和市场竞争力。为了确保软件的可用性和可靠性,软件测评成为一个不可或缺的环节,软件测评报告也是对软件产品进行全面评估后形成的一份文档,旨在系统地纪录…