Python 之 __file__ 变量导致打包 exe 后路径输出不一致的问题

现象

做项目的时候,一直使用 os.path.dirname(os.path.abspath(__file__)) 来获取当前目录。然而,最近却遇到了一个路径相关的问题。直接运行 py 文件是正常的,但是打包成 exe 之后,却显示因为路径问题导致程序报错无法继续执行。

比如我有一段获取当前目录的脚本代码:

test.py

import os
import timedef get_current_dir():return os.path.dirname(os.path.abspath(__file__))if __name__ == '__main__':current_dir = get_current_dir()print(current_dir)  # E:\lky_project\tmp_project\test_projecttime.sleep(10)

正常用 Python 解释器执行的话输出 E:\lky_project\tmp_project\test_project,看起来没什么问题。

好,接下来,我用下面的命令对 test.py 打包,打包后将生成的 test.exe 移动到和 test.py 相同的目录下(确保执行目录一致)。

E:\lky_project\tmp_project\test_project> pyinstaller -F ./test.py

然后双击运行 test.exe,结果输出的目录却是下面这种(看起来是个临时目录)。

显然,这两个输出不是同一个目录,而我中间只是做了打包的操作,并没有对代码进行任何额外修改,但为什么输出的目录却不一样呢?

原因

我搜了一下 DeepSeek,其中的分析我还是比较认同的,所以就不多说了。分析的原因如下:

  • __file__ 变量通常是指当前执行脚本的路径。当直接运行脚本时,__file__ 会返回该脚本的文件名,然后通过 os.path.abspath 获取绝对路径,再取目录名,得到的就是脚本所在的目录路径。这应该是正确的。
  • 但是当打包成 exe 后,比如使用 PyInstaller,情况可能会不同。PyInstaller 打包后的 exe 文件会将脚本解压到一个临时目录中运行,这时候 __file__ 可能指向的是这个临时目录中的路径,而不是原来的脚本位置。这就会导致 current_dir 在打包后得到的是临时目录的路径,而不是用户期望的 exe 所在的目录。

解决

既然原因找到了,总得找个解决方案。

sys.frozen

其中一个解决方法,利用程序打包前和打包后 sys.frozen 环境变量的不同来进行区分,不同情况使用不同的目录获取方式。

import sys
import os
import timedef get_current_dir():if getattr(sys, 'frozen', False):# 打包后的情况,使用 sys.executable 的目录print("frozen")return os.path.dirname(sys.executable)else:# 打包前,正常脚本执行print("not frozen")return os.path.dirname(os.path.abspath(__file__))current_dir = get_current_dir()
print(current_dir)time.sleep(10)

os.getcwd()

再有就是使用 os.getcwd() 来获取当前目录。

import os
import timedef get_current_dir():return os.path.abspath(os.getcwd())current_dir = get_current_dir()
print(current_dir)time.sleep(10)

pathlib

或者使用 pathlib 的 absolute() 或 resolve() 方法也可以。

import time
import pathlibdef get_current_dir():# return pathlib.Path("./").resolve()return pathlib.Path("./").absolute()current_dir = get_current_dir()
print(current_dir)time.sleep(10)

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

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

相关文章

PH热榜 | 2025-04-21

1. Google Whisk 2.0 标语:将图像转换为八秒的动画短片。 介绍:Whisk 是谷歌实验室的一项新创新,现在推出了 Whisk Animate——它可以将你的图片转换成生动的8秒视频,采用了 Veo 2 技术。此功能现已在60多个国家的 Google One A…

AI大模型 —— 国产大模型 —— 华为大模型

有这么一句话,那就是AI大模型分两种,一种是大模型;另一种是华为大模型。 如果从技术角度来分析,华为的技术不论是在软件还是硬件都比国外的大公司差距极大,甚至有些技术评论者认为华为的软硬件技术至少落后2.5代&#…

FPGA 中 XSA、BIT 和 DCP 文件的区别

在 FPGA(现场可编程门阵列)开发中,XSA、BIT 和 DCP 文件是常见的文件类型,它们在功能、用途、文件内容等方面存在明显区别,以下是详细介绍: 1. XSA 文件 定义与功能 XSA(Xilinx Shell Archiv…

MH2103系列coremark1.0跑分数据和优化,及基于arm2d的优化应用

CoreMark 1.0 介绍 CoreMark 是由 EEMBC(Embedded Microprocessor Benchmark Consortium)组织于 2009 年推出的一款用于衡量嵌入式系统 CPU 或 MCU 性能的标准基准测试工具。它旨在替代陈旧的 Dhrystone 标准(Dhrystone 容易受到各种libc不同…

云原生与AI的关系是怎么样的?

云原生与AI的结合正在重塑现代应用的开发与部署模式,两者相辅相成,共同推动技术创新与产业升级。以下是两者的核心概念、结合点及未来趋势的详细解析: 一、云原生与AI的核心概念 云原生(Cloud Native) • 定义&#…

【CentOs】构建云服务器部署环境

(一) 服务器采购 2 CPU4G 内存40G 系统盘 80G 数据盘 (二) 服务器安全组和端口配置 (三) 磁盘挂载 1 登录 root 2 查看目前磁盘使用情况 df -h 3 查看磁盘挂载情况 识别哪些磁盘没挂载 fdisk -l 4 对未挂载磁盘做分区 fdisk /dev/vdb 输入m&#xff0…

LangChain4j语言模型选型指南:主流模型能力全景对比

LangChain4j语言模型选型指南:主流模型能力全景对比 前言 在大语言模型应用开发中,选择合适的底层模型提供商是架构设计的关键决策。LangChain4j作为Java生态的重要AI框架,其支持的20模型提供商各有独特的优势场景。本文通过功能矩阵深度解…

2025.4.21日学习笔记 JavaScript String、Array、date、math方法的使用

1. String(字符串) String 对象用于处理和操作文本数据。 length:返回字符串的长度。 const str "Hello"; console.log(str.length); // 输出: 5 charAt(index):返回指定索引位置的字符。 const str "Hello…

(14)VTK C++开发示例 --- 将点投影到平面上

文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容👉内容导航 👈👉VTK开发 👈 1. 概述 计算一个点在一个平面上的投影。 vtkPlane 是 VTK(Visualization Toolkit)库中的一个类&…

电子电器架构 ---软件定义汽车的电子/电气(E/E)架构

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

Android开发中的复制和粘贴

Android 提供了一个强大的基于剪贴板的框架,用于复制和粘贴。它支持简单和复杂的数据类型,包括文本字符串、复杂数据结构、文本和二进制流数据,以及应用资源。简单的文本数据直接存储在剪贴板中,而复杂的数据则存储为引用&#xf…

【STM32单片机】#10.5 串口数据包

主要参考学习资料: B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…

百度暑期实习岗位超3000个,AI相关岗位占比87%,近屿智能携AIGC课程加速人才输出

今年3月,百度重磅发布3000暑期实习岗位,聚焦大模型、机器学习、自动驾驶等AI方向的岗位比例高达87%。此次实习岗位涉及技术研发、产品策划、专业服务、管理支持、政企解决方案等四大类别,覆盖超300个岗位细分方向。值得一提的是,百…

vue3 + element-plus中el-dialog对话框滚动条回到顶部

对话框滚动条回到顶部 1、需要对话框显示后 2、使用 nextTick 等待 Dom 更新完毕 3、通过开发者工具追查到滚动条对应的标签及class“el-overlay-dialog” 4、设置属性 scrollTop 0 或者 执行方法 scrollTo(0, 0) // 对话框显示标识 const dialogVisible ref(false); //…

C++学习之游戏服务器开发十一DOCKER的基本使用

目录 1.多实例部署方案 2.容器的概念 3.docker初识 4.docker仓库 5.docker镜像 6.docker容器 7.docker和虚拟机的区别 8.docker命令解释 9.dockerfile构建镜像 10.离线分发镜像 1.多实例部署方案 redis 命令( redis-cli XXXX ) set key value:…

2025.4.21总结

工作:开了一场关于大模型版本的会议,回归一个问题单,提了两个单,把用例都执行完。如今都四月中旬了,上班年快要结束了,该到了冲刺KPI的时候了。 今日思考:刷到了jack叔叔的视频,讲了…

vite安装及使用

没特殊要求的项目,还是怎么简单怎么来╮(╯▽╰)╭ 一、Vite 基础知识 1. 什么是 Vite? Vite 是一个前端构建工具,专注于开发服务器速度和优化构建过程。特点: 快速冷启动:利用 ES 模块的原生支持,实现快速的开发服务器启动。即时热更新:在开发过程中,修改代码后可以…

ubuntu下gcc/g++安装及不同版本切换

1. 查看当前gcc版本 $ gcc --version# 查看当前系统中已安装版本 $ ls /usr/bin/gcc*2. 安装新版本gcc $ sudo apt-get update# 这里以版本12为依据(也可以通过源码方式安装,请自行Google!) $ sudo apt-get install -y gcc-12 g…

cdq 系列 题解

从二维数点&#xff08;二维偏序&#xff09;到三维偏序。 用 cdq 分治可以解决二维数点问题。 1.洛谷 P1908 逆序对 题意 求所有数对 ( i , j ) (i,j) (i,j) 的个数&#xff0c;满足 i < j i<j i<j 且 a i > a j a_i>a_j ai​>aj​。 1 ≤ n ≤ 5 1…

计算机组成与体系结构:内存接口(Memory Interface)

目录 什么是内存接口 &#xff1f; 为什么需要特别设计“接口”&#xff1f; 什么是 MIPS&#xff1f;为什么它和内存接口有关&#xff1f; 内存接口的两种访问方式 串行访问&#xff08;Serial Access Model&#xff09; 并行访问&#xff08;Parallel Access Model&…