pyinstaller打包找不到文件的问题解决

1、将python程序打包成单文件(使用 -F 参数)后,尝试运行外部文件却提示找不到的问题

当你将python程序打包成单文件(使用 -F 参数)后,运行程序,它实际上是先将exe内的资源文件解压到临时文件夹,然后再运行的,所以会导致这种问题

比如,当你在程序里面调用一个外部exe时,但却提示找不到该exe文件。

例子(这里我用win32api去隐式运行外部exe文件):

import win32api
win32api.ShellExecute(0, 'open', 'nginx.exe', '', '', 0)

首先,你需要将这个外部的exe文件添加进pyinstaller的打包里。

有两种方法:

1、直接用参数添加:

--add-data "nginx.exe;."

完整命令:pyinstaller -F main.py --add-data "nginx.exe;."

2、在spec文件添加:

每次执行pyinstaller打包命令后会生成spec文件,打开它
在里面找到data=[] 列表,添加元素,变成了:datas=[('nginx.exe', '.')]
然后用spec打包:pyinstaller main.spec
我解释一下这个点“.”是什么意思:

由于使用单文件打包出来的exe会先解压再运行,所以点“.” 其实表示你打包的这个exe文件运行解压的完整路径

如:C:\...\temp(临时文件夹)\asdqwezxc(你程序运行时自动解压到的目录)

  • 所以这个nginx.exe 被打包后,会解压到 C:\...\temp\asdqwezxc\nginx.exe
  • 如果把点“.”改为test,就会解压到 C:\...\temp\asdqwezxc\test\nginx.exe
  • 以此类推

好,现在nginx.exe已被打包。然后要注意一个问题:

打包出来的exe在运行时,它的工作路径和它解压到的路径,是不一样的!

你可以测试一下:

import os
print(os.getcwd())

可以发现,打印出来的工作路径并不是它运行时解压到的路径!
而是这个打包出来的exe,它本身所存在的路径!

问题来了:

诸如open('xxx.txt')这些操作文件的函数,一般首先都是在工作路径查找你所指定的文件的。

所以,当我们直接这样执行已打包的外部文件时,程序会报找不到文件!所以请使用它的解压路径。

下面提供一个函数,可以很方便的获取到解压路径:

import os, sys
def base_path(path):
  if getattr(sys, 'frozen', None):
    basedir = sys._MEIPASS
  else:
    basedir = os.path.dirname(__file__)
  return os.path.join(basedir, path)

print(base_path(''))
print(base_path('test\gg.exe'))

第一句打印会显示完整的解压路径:

C:\...\temp\asdqwezxc\

第二句打印是这样的:

C:\...\temp\asdqwezxc\test\gg.exe

所以当我们在调用已打包的外部文件时,应该先使用os.chdir()将工作路径改为解压路径:

再进行操作,就不会报文件找不到了

os.chdir(base_path(''))
win32api.ShellExecute(0, 'open', 'nginx.exe', '', '', 0)

不过要注意的是,如果你要写出文件到程序所在的目录(非解压目录),那么你得把工作目录改回来,否则文件会被写出到解压路径(临时文件夹)。

稍微封装一下就好了:

import os, sys

def base_path(path):
  if getattr(sys, 'frozen', None):
    basedir = sys._MEIPASS
  else:
    basedir = os.path.dirname(__file__)
  return os.path.join(basedir, path)

tmd = base_path('') # 这是解压路径
cwd = os.getcwd() # 这是程序的所在路径

# 当需要调用打包的外部文件时
os.chdir(tmd) # 先把工作路径变成解压路径
do() # 执行你要干的事情

# 当需要写出文件到程序所在目录时
os.chdir(cwd) # 把工作路径切换回来
do() # 执行你要干的事情

2、当你使用cython将py文件编译成pyd文件后使用pyinstaller打包,提示找不到模块的问题
直接使用pyinstaller打包py文件是很容易导致源码被反编译的

所以在打包的时候最好将py文件编译成pyd文件,这样可以很大程度上防止反编译。

为什么呢?因为pyd文件的来历是这样的:

py文件 → c文件 → pyd文件
所以直接反编译pyd只能得到上一步cython生成的c文件,而无法得到我们的py源文件。

如何打包pyd成文件请看这篇文章:https://www.jb51.net/article/184725.htm
接下来回到我们的问题。

解决方法很简单,请看:

比如说,我有一个文件main.py,引入了位于同级目录下的test.py模块

# main.py:就像这样直接引入
import test

现在我将test.py 编译成pyd文件,生成了:test.cp37-win_amd64.pyd

这个pyd文件名除了我们原本的文件名test,还会带上编译环境的名称,这个环境后缀名我们可以不用管 ,因为python引入模块还是很智能的(会自动引入.pyd文件,因为它的优先级高于.py文件)。

这么智能,但是为什么我用pyinstaller打包时就提示找不到文件?
其实我们需要在打包时--hidden-import这些模块

1、直接添加

在打包时添加--hidden-import test即可
完整命令:pyinstaller -F --hidden-import test

2、使用spec文件

同样的,运行一次pyinstaller打包命令后会生成spec文件,打开它
找到hiddenimports=[],添加test模块,变成了:hiddenimports=['test']
很简单对吧?
而且除了我们自己写的一些py模块,其它模块在打包时可能也会提示找不到,都可以用这个方法解决。

3、打包成单文件时(使用-F参数),运行时要求管理员权限的参数--uac-admin无效的问题
请看我的这篇文章:pyinstaller打包单文件时–uac-admin选项不起作用怎么办

本质上大概也是因为找不到文件。

4、无控制台打包(使用-w参数),运行时弹框提示Failed to execute script的问题
请看我的这篇文章:pyinstaller打包成无控制台程序时运行出错,与popen冲突的解决方法

这个问题一般是程序内有输入导致的,这个输入可以是input(),也可以是其它的一些stdin操作(如os.popen实际上会造成输入请求)

本质上就是:使用-w参数(无控制台)打包时程序里不要请求输入

当然,实在要用输入,又不想要控制台怎么办?很简单,把控制台隐藏了就行!

下列两个方法,试试看:

import ctypes
def hideConsole():
  """
  Hides the console window in GUI mode. Necessary for frozen application, because
  this application support both, command line processing AND GUI mode and theirfor
  cannot be run via pythonw.exe.
  """

  whnd = ctypes.windll.kernel32.GetConsoleWindow()
  if whnd != 0:
    ctypes.windll.user32.ShowWindow(whnd, 0)
    # if you wanted to close the handles...
    #ctypes.windll.kernel32.CloseHandle(whnd)

def showConsole():
  """Unhides console window"""
  whnd = ctypes.windll.kernel32.GetConsoleWindow()
  if whnd != 0:
    ctypes.windll.user32.ShowWindow(whnd, 1)

暂时就这么多呃,都是本人在打包过程中实际上遇到过的问题和经验。。基本可用

到此这篇关于pyinstaller打包找不到文件的问题解决的文章就介绍到这了,更多相关pyinstaller打包找不到文件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Pyinstaller 打包exe教程及问题解决

    安装 pip insatll Pyinstaller 参数 pyinstaller -Fw main.py 参数 概述 -F,-onefile 打包一个单个文件,如果你的代码都写在一个.py文件的话,可以用这个,如果是多个.py文件就别用 -D, –onedir 打包多个文件,在dist中生成很多依赖文件,适合以框架形式编写工具代码,我个人比较推荐这样,代码易于维护 -K, –tk 在部署时包含 TCL/TK -a, –ascii 不包含编码.在支持Unicode的python版本上默认包含所有

  • pyinstaller打包程序exe踩过的坑

    基础环境 python 2.7.17 pyinstaller 3.5 安装pyinstaller pip install pyinstaller 坑,大坑,深坑 背景:用pygame写了个贪吃蛇游戏,要打包成exe 用到了字体文件 C:\Windows\Fonts\simsun.ttc (宋体) 打包过程中没有报错 打包过程中的警告可以忽略,这个警告: WARNING: Hidden import "pygame._view" not found! 运行exe的时候报NotImplem

  • Pyinstaller将py打包成exe的实例

    背景:分享python编写的小脚本时,拷贝代码还缺各种环境,使用Pyinstaller将py可以打包成exe,直接运行即可 1.安装pyinstaller运行时所需要的windows拓展pywin32 2.安装pyinstaller pip install pyinstaller 验证是否成功:pyinstaller -v 3.pyinstaller指令 参数 含 义 -F 只生成一个exe文件 –distpath 指定生成的exe存放的目录 –workpath 指定编译中临时文件存放的目录 -

  • 利用pyinstaller将py文件打包为exe的方法

    写在前面 做大创的时候,因为需要计算合金的各种能量.温度等一大堆数据,为了能够福泽后来的学弟学妹,我决定将我处理数据时用的python程序打包成exe,这样就可以在没有安装python环境的电脑上运行我的程序了.所以上网查了一大堆如何打包的方法,尝试了py2exe和pyinstaller这两种方法,发现还是后者更加的简单便捷.同时为了能够帮助我自己以后再想用到的时候有一个教程可以查找,我就写了这一篇博客出来,留作纪念. 前提条件 首先我们需要两个东西:python3.4版本,pyinstalle

  • Pyinstaller打包.py生成.exe的方法和报错总结

    Pyinstaller 打包.py生成.exe的方法和报错总结 简介 有时候自己写了个python脚本觉得挺好用想要分享给小伙伴,但是每次都要帮他们的电脑装个python环境.虽然说装一下也快,但是相对来说效率还是不高,要是能将python的**.py文件转化为.exe**,那么世界将变得更美好.这篇文章我将简单的介绍如何使用Pyinstaller来打包我们的python脚本. 安装 Pyinstaller pyinstaller的官网为:http://www.pyinstaller.org/

  • python-pyinstaller、打包后获取路径的实例

    使用pyinstaller可以把.py文件打包为.exe可执行文件,命令为: pyinstaller hello.py 打包后有两个文件夹,一个是dist,另外一个是build,可执行文件在dist文件夹里面,但是会有许多依赖是独立文件存在 pyinstaller -F hello.py 使用-F参数后,打包的可执行文件是一个整体,只有一个.exe文件. 获取文件路径的方式有四种,可以在打包成exe文件后,获取.exe文件的当前路径 import sys import os print(sys.

  • python pyinstaller打包exe报错的解决方法

    今天用python 使用pyinstaller打包exe出现错误 环境pyqt5 + python3.6 32位 在导入pyqt5包之前加上如下代码 import sys import os if hasattr(sys, 'frozen'): os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH'] from PyQt5.QtWidgets import QApplication, QMainWindow from py

  • 如何使用pyinstaller打包32位的exe程序

    说明:原来安装的python为64位,故安装的pyinstaller和打包后的exe都为64位.而64位的exe文件在32位的win7操作系统下是无法执行的,显示不兼容.网上查询发现,简单(可能不方便)的方法是采用32位的python重新打包.这里,我使用的是conda构建32位python环境,然后再次打包.安装Anaconda的方法,感兴趣的可以查看.具体操作如下: 构建32位python环境 进入命令提示符窗口 set CONDA_FORCE_32BIT=1 //切换到32位 conda

  • 利用pyinstaller打包exe文件的基本教程

    前言 PyInstaller可以用来打包python应用程序,打包完的程序就可以在没有安装Python解释器的机器上运行了.PyInstaller支持Python 2.7和Python 3.3+.可以在Windows.Mac OS X和Linux上使用,但是并不是跨平台的,而是说你要是希望打包成.exe文件,需要在Windows系统上运行PyInstaller进行打包工作:打包成mac app,需要在Mac OS上使用. 方法如下: 1.确保已安装python解释器 2.确认pip是否是最新版本

  • pyinstaller打包找不到文件的问题解决

    1.将python程序打包成单文件(使用 -F 参数)后,尝试运行外部文件却提示找不到的问题 当你将python程序打包成单文件(使用 -F 参数)后,运行程序,它实际上是先将exe内的资源文件解压到临时文件夹,然后再运行的,所以会导致这种问题 比如,当你在程序里面调用一个外部exe时,但却提示找不到该exe文件. 例子(这里我用win32api去隐式运行外部exe文件): import win32api win32api.ShellExecute(0, 'open', 'nginx.exe',

  • pyinstaller打包多个py文件和去除cmd黑框的方法

    1.打包多个py文件并且去除cmd黑框 格式:pyinstaller.exe -F 路径\文件名.py空格路径\文件名.py空格--noconsole 以上这篇pyinstaller打包多个py文件和去除cmd黑框的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 关于pyinstaller 打包多个py文件的问题

    目录 安装pyinstall 注意事项 参数详解 pyinstaller最佳使用方式 第一步,通过上面的命令执行打包,此时会生成相应的spec文件 第二步:对xxx.spec文件执行pyinstaller 指令 spec文件解析 手动修改spec文件 笔记: pyinstaller的常见问题 尝试解决1: 尝试解决1,测试结果: 以下上是给我启发的网友的操作方式,记录并感谢 实验项目结构 遇到的问题 Python 中的 exit() 和 sys.exit() 的区别 安装pyinstall pi

  • 如何对Python编译PyInstaller打包生成的exe文件进行反编译生成pyc、py源代码文件

    目录 准备工作 根据exe生成pyc文件 根据pyc文件反编译为py文件 参考 总结 准备工作 没有加壳的python编译并打包的exe文件 python反打包代码(不知道这样叫是否合理):python-exe-unpacker 16进制编辑查看器 :Hex Editor Neo 反编译库 :uncompyle6 根据exe生成pyc文件 下载并解压缩 python-exe-unpacker 代码,myfile.exe为需要反编译的exe文件 使用python运行 python-exe-unpa

  • pyinstaller打包可执行文件,存放路径包含中文无法运行的解决方案

    一.实验环境 1.Windows7x64_SP1 2.anaconda2.5.0 + python2.7(anaconda集成,不需单独安装) 3.pyinstaller3.0 二.问题描述 1.使用如上环境,pyinstaller打包生成的exe文件,存放在本地,如果路径中包含中文,程序无法运行:exe程序如果使用中文命名,程序同样无法运行. 三.解决方式 1.查看pyinstaller网站 https://pypi.org/project/PyInstaller/ 2.有如下描述 3.更换实

  • 完美解决pyinstaller打包报错找不到依赖pypiwin32或pywin32-ctypes的错误

    报错信息 最近闲来无事,用python的tkinter库开发了一款带日程提醒的万年历桌面程序.在程序开发结束开始打包时,却发现一直报错 PyInstaller cannot check for assembly dependencies. Please install PyWin32 or pywin32-ctypes. pip install pypiwin32 但是运行pip install pypiwin32时却提示两个库都已经安装过了 可是当再运行打包脚本时就是死活无法打包,就是提示缺少

  • 解决pyinstaller 打包exe文件太大,用pipenv 缩小exe的问题

    解决pyinstaller 打包exe文件太大,用pipenv 缩小exe的问题 最近写一个小脚本,源代码200多行,引入了 openpyxl.requests库,写完打包exe之后居然有64MB的大小,真是奇了葩了.网上查找各位大神的做法,自己又动手填了N个坑之后,总算找到缩小exe文件的方法了,这种方法必须使用到pipenv,详细记录如下: 1.安装pipenv 就像安装其他python库一样,在cmd环境下安装: pip install pipenv 2.安装完成后,随便找一个盘符,在这个

  • pyinstaller打包exe程序的步骤和添加依赖文件的实现

    目录 pyinstaller打包exe程序和添加依赖文件 1.安装pyinstaller库 2.pyinstaller的打包机制 3.打包命令 4.添加导包外的一些依赖文件 5..spec方式打包 6.pyinstaller常用参数 pyinstall打包时的依赖问题 pyinstaller打包exe程序和添加依赖文件 或许我们并不是专业的程序猿,但是却可以通过python来提高我们的工作效率,减少加班时间,让代码替我们完成一些重复的工作,节省下来的时间去泡个妹子,牵牵小手不香吗 话不多说,马上

  • python非单一.py文件用Pyinstaller打包发布成exe

    目录 一:背景以及项目结构介绍 二:实施步骤 1:总体思路 2:安装pyinstaller 3:具体步骤(以我项目为例子) 三:疑难杂症和需要注意的坑 1:打包找不到模块问题 2:打包后,一直提示Failed to execute scrpt xxx问题 3:cmd下运行打包好的exe,运行一段时间卡主不动,按一下回车才继续 4:其他注意事项 一:背景以及项目结构介绍 第一次将自己做的python爬虫项目打包成exe,搜了很多网上教程,大部分都是打包一个py文件的小demo,这里先给个笑脸吧,除

  • 使用Pyinstaller打包exe文件详细图文教程

    目录 前言 场景说明 pyinstaller安装 打包参数 打包问题解决方法汇总 总结 前言 在业务场景中, 经常需要Python开发一些小程序/脚本/GUI界面,交付给一些小白或未安装Python 的小伙伴们使用.噔噔蹬蹬 pyinstaller 闪亮登场 场景说明 使用Pyinstaller将Python脚本或者项目打包,生成可执行的.exe文件. Pyinstaller是一个很不错的免费打包工具,支持Windows,Linux和MacOS,完美支持32位和64位系统. 除了Pyinstal

随机推荐