一种优雅的方法获取PyInstaller打包Python程序的资源路径和目录路径

news2024/9/22 18:31:57

1、需求分析

运行Python程序的时候需要获取的资源有2种: 一种是固定的资源文件,你希望启动程序的时候可以调用的,比如数据库文件和图片资源文件;另一种是用于存储历史记录的文件,你希望每次打开都会改变其中的内容,存储记录信息,而不是每次运行获取到相同的状态。

运行Python的方式有3种: 一种是直接运行py脚本,一种是以多文件模式打包成exe文件运行,一种是以单文件模式打包成exe文件运行。单文件exe运行,实际上是将资源文件解压到某个临时文件夹,然后再启动运行。

启动Python程序时的工作路径有2种: 一种是在当前目录启动Python程序,一种是在非当前目录启动程序。在当前目录启动是更简单的场景,在程序目录双击打开就是。但是在非当前目录启动程序是更通用的场景,这个问题能够解决,前者自然能够解决。

启动Python程序时的程序路径有2种: 一种是使用绝对路径,一种是使用相对论路径。

所以,排列组合,总共有2×3×2×2=24种组合情况,我希望在这24种情况内都有符合预期的表现。

2、网上的做法

如果使用PyInstaller打包Python程序,需要包含资源文件,需要在打包命令中添加 --add-data 参数,例如:

pyinstaller main.py --add-data="resource.jpg;."

但为了在py脚本和exe程序中能够兼容运行代码,网上一般给出的解决方案是这样的:

import os
import sys

resource_path = 'resource.jpg'
if hasattr(sys, '_MEIPASS'):
    resource_path = os.path.join(sys._MEIPASS, resource_path)

3、优雅的做法

最近我发现有一个更优雅的解决方案:

resource_path = __file__ + '/../resource.jpg'

这样可以解决在单文件打包和直接运行情况下静态资源路径不同的问题。

然而对于存储历史记录的资源文件,如果使用单文件打包模式,在窗口关闭时会清除临时文件,会将这个记录文件也一起删除掉,这自然是不符合预期的。

如果直接写一个路径,例如:

history_path = 'history.txt'

当你在程序文件夹内启动该程序时,临时文件会创建在程序文件夹的目录内,这是符合预期的。

但是在其他工作路径启动这个程序,例如在使用自启动功能启动程序、在“运行”中启动程序时,程序的“工作路径”不是exe文件的所在文件夹,临时文件就会产生到意想不到的地方。

但我发现一种优雅的写法可以是:

history_path = sys.argv[0] + '/../history.txt'

原理就是 sys.argv[0] 是从工作目录到程序目录之间的相对路径(或绝对路径),所以以这样的相对地址查找,能够准确定位到“程序位置”。

3.1 Mac的Bug

我在Mac上运行的时候,发现OSX竟然不支持 /../ 这种相对路径的表达方法:

Mac截屏

还得在外面套一层,解算出真实路径:

resource_path = os.path.realpath(__file__ + '/../resource.jpg')

其中 realpath 表示计算真实路径,可以将符号链接消除,找到文件实际存储的位置。

也可以替换为 relpath(相对路径)、或 abspath(绝对路径),这三种没有太大的区别。

附、Python中的“路径”

Python中有若干和“路径”有关的参数或者方法,它们的获取方式及其返回结果对比:

获取方法py脚本多文件exe单文件exe
__file__<程序目录>\main.py 或相对路径<程序目录>\main.py<临时目录>\main.py
os.getcwd()<工作目录><工作目录><工作目录>
sys.argv[0]<程序目录>\main.py 或相对路径<程序目录>\main.exe 或相对路径<程序目录>\main.exe 或相对路径
sys.path[0]<程序目录><程序目录>\base_library.zip<临时目录>\base_library.zip
sys.executable<Python安装目录>\python.exe<程序目录>\main.exe<程序目录>\main.exe

注:当在程序文件夹内启动程序时, <工作目录><程序目录> 是同一位置。

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

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

相关文章

【机器学习】智能驱动未来:机器学习在能源效率提升与环境管理中的创新应用

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#x1f4d2;2. 机器学习能源环境领域的应用潜力&#x1f304;能源效率提升&#x1f3de;️环境管理⛰️具体案例…

动漫风格动漫404网站维护HTML源码

源码介绍 动漫风格动漫404网站维护HTML源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 效果预览 源码下载 动漫风格动漫404网站维护HTML源码

收银系统源码-千呼新零售收银视频介绍

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

XMl基本操作

引言 使⽤Mybatis的注解⽅式&#xff0c;主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能&#xff0c;建议使⽤XML来配置映射语句&#xff0c;也就是将SQL语句写在XML配置⽂件中. 之前&#xff0c;我们学习了&#xff0c;用注解的方式来实现MyBatis 接下来我们…

传输层和网络层的关系,ip协议+ip地址+ip报头字段介绍(4位TOP字段,8位生存时间(ttl)),ip地址和端口号的作用

目录 传输层和网络层的关系 引入 介绍 ip协议 介绍 ip地址 引入 数据传递过程 举例(ip地址的作用) ip报头 格式 4位版本号 ip地址不足的问题 8位服务类型 4位TOP(type of service)字段 最小延时 最大吞吐量 4位首部长度 16位总长度 8位协议号 首部校验和…

科研绘图系列:R语言分割小提琴图(Split-violin)

介绍 分割小提琴图(Split-violin plot)是一种数据可视化工具,它结合了小提琴图(violin plot)和箱线图(box plot)的特点。小提琴图是一种展示数据分布的图形,它通过在箱线图的两侧添加曲线来表示数据的密度分布,曲线的宽度表示数据点的密度。而分割小提琴图则是将小提…

LeNet实验 四分类 与 四分类变为多个二分类

目录 1. 划分二分类 2. 训练独立的二分类模型 3. 二分类预测结果代码 4. 二分类预测结果 5 改进训练模型 6 优化后 预测结果代码 7 优化后预测结果 8 训练四分类模型 9 预测结果代码 10 四分类结果识别 1. 划分二分类 可以根据不同的类别进行多个划分&#xff0c;以…

【数据分享】2013-2022年我国省市县三级的逐月SO2数据(excel\shp格式\免费获取)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000——2022年的省市县三级的逐月PM2.5数据和2013-2022年的省市县三级的逐月CO数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次我们分享的是我国2013——2022年的省…

Langchain-Chatchat-Ubuntu服务器本地安装部署笔记

Langchain-Chatchat&#xff08;原Langchain-ChatGLM&#xff09;基于 Langchain 与 ChatGLM 等语言模型的本地知识库问答 | Langchain-Chatchat (formerly langchain-ChatGLM), local knowledge based LLM (like ChatGLM) QA app with langchain。 开源网址&#xff1a;https:…

基于NeRF的路面重建算法——RoME / EMIE-MAP / RoGS

基于NeRF的路面重建算法——RoME / EMIE-MAP / RoGS 1. RoMe1.1 Mesh Initialization / Waypoint Sampling1.2 Optimization1.3 Experiments 2. EMIE-MAP2.1 Road Surface Representation based on Explicit mesh and Implicit Encoding2.2 Optimizing Strategies2.3 Experimen…

基于面向对象和递归的拦截器设计模式

1 定义 拦截器模式&#xff08;Interceptor Pattern&#xff09;&#xff0c;是指提供一种通用的扩展机制&#xff0c;可以在业务操作前后提供一些切面的&#xff08;Cross-Cutting&#xff09;的操作。这些切面操作通常是和业务无关的&#xff0c;比如日志记录、性能统计、安…

SciPy版本与Python和NumPy各个版本的兼容性

但是现在我用Scipy1.13.1&#xff0c;Python3.10&#xff0c;NumPy2.0.0&#xff0c;使用Scipy时会报错&#xff0c;将NumPy 版本降低为1.26.4以后&#xff0c;就没有报错了。

C++ | Leetcode C++题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; class Solution { public:int missingNumber(vector<int>& nums) {int n nums.size();int total n * (n 1) / 2;int arrSum 0;for (int i 0; i < n; i) {arrSum nums[i];}return total - arrSum;} };

【MySQL】一些业务场景常见的查询,比如实现多表字段同步,递归查询等

目录 快速加注释多表关联查询更新多个字段循环查询子级方法1&#xff1a;递归查询方法2&#xff1a;循环查询 快速加注释 使用ALTER TABLE语句可以修改表结构&#xff0c;包括添加注释。以下是添加注释的语法&#xff1a; ALTER TABLE 表名 MODIFY COLUMN 列名 列类型 COMMEN…

【开源库学习】libodb库学习(三)

4 查询数据库 如果我们不知道我们正在寻找的对象的标识符&#xff0c;我们可以使用查询在数据库中搜索符合特定条件的对象。ODB查询功能是可选的&#xff0c;我们需要使用--generate-query ODB编译器选项显式请求生成必要的数据库支持代码。 ODB提供了一个灵活的查询API&#x…

LeetCode 热题 HOT 100 (001/100)【宇宙最简单版】

【链表】 No. 0160 相交链表 【简单】&#x1f449;力扣对应题目指路 希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; ⭐题目描述&#xff1a;两个单链表的头节点 headA 和 …

51单片机嵌入式开发:13、STC89C52RC 之 RS232与电脑通讯

STC89C52RC 之 RS232与电脑通讯 第十三节课&#xff0c;RS232与电脑通讯1 概述2 Uart介绍2.1 概述2.2 STC89C52UART介绍2.3 STC89C52 UART寄存器介绍2.4 STC89C52 UART操作 3 C51 UART总结 第十三节课&#xff0c;RS232与电脑通讯 1 概述 RS232&#xff08;Recommended Stand…

huawei USG6001v1学习----NAT和智能选路

目录 1.NAT的分类 2.智能选路 1.就近选路 2.策略路由 3.智能选路 NAT:&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09; 指网络地址转换&#xff0c;1994年提出的。NAT是用于在本地网络中使用私有地址&#xff0c;在连接互联网时转而使用全局…

Java | Leetcode Java题解之第263题丑数

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isUgly(int n) {if (n < 0) {return false;}int[] factors {2, 3, 5};for (int factor : factors) {while (n % factor 0) {n / factor;}}return n 1;} }

数学建模--优劣解距离法TOPSIS

目录 简介 TOPSIS法的基本步骤 延伸 优劣解距离法&#xff08;TOPSIS&#xff09;的历史发展和应用领域有哪些&#xff1f; 历史发展 应用领域 如何准确计算TOPSIS中的理想解&#xff08;PIS&#xff09;和负理想解&#xff08;NIS&#xff09;&#xff1f; TOPSIS方法在…