PyInstaller打包python程序为exe可执行文件

教程千千万,貌似我的window电脑就是打包不了,而且不同电脑的表现都不一致,很是奇怪。


文章目录

  • 1 极简版
    • 1.1 生成文件`spec`详解
    • 1.2 是否变成一个exe主文件
  • 2 虚拟环境打包
  • 3 其他打包需求
    • 3.1 加密打包
    • 3.2 Pyinstaller打包多个py文件为一个exe文件
  • 4 如何反编译
  • 5 一些报错
    • 5.1 utf-8' codec can't decode byte 0xce in position
    • 5.2 exe文件要从dist文件拿出来
    • 5.3 windows打包会将所有之前的依赖统统整上
    • 5.4 pyinstaller的版本一定要保证最新
    • 5.5 A RecursionError (maximum recursion depth exceeded) occurred
    • 5.6 模块找不到的问题解决办法


官方地址:
https://github.com/pyinstaller/pyinstaller
官方文档:https://pyinstaller.org/en/stable/

python版本要求: Python version 3.8-3.12.

1 极简版


pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyinstaller #清华源

然后


Pyinstaller -F py_word.py 打包exe
Pyinstaller -F -w py_word.py 不带控制台的打包
Pyinstaller -F -w -i chengzi.ico py_word.py 打包指定exe图标打包

这里的参数设定:
在这里插入图片描述

来看看生成的文件都是什么:

  • 同名的.spec:重要配置文件,.spec文件中主要包含4部分:Analysis、PYZ、EXE、COLLECT:
    • Analysis:主要是分析py文件的依赖信息
    • PYZ:是一个.pyz的压缩包,包含程序运行需要的依赖
    • EXE:是根据上述两项内容而生成的
    • COLLECT:主要是输出信息
  • dist文件夹:最终的exe文件存放位置,可能要从dist拿出来
  • build文件夹:中间过程,创建好之后可以直接删除

1.1 生成文件spec详解

参考:
https://blog.csdn.net/kevinshift/article/details/104880101

其实如果你自己会写.spec,可以直接通过pyinstaller xx.spec来执行打包

# -*- mode: python ; coding: utf-8 -*-
a = Analysis(['gui.py'],pathex=['D:\\gui'],binaries=[],datas=[('D:\\gui\\config.ini','.'),('D:\\gui\\清洗规则.xlsx','.')],hiddenimports=['pandas'],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)

datas里边的元素是以元组的形式来存储的,有这么一个映射关系:

datas = [('源文件路径','目标路径')]

如果有多个,就多放几个元素,内容不限,如果目标路径是打包后的根目录,那就写.
修改好之后,运行这条命令即可:

pyinstaller  xx.spec

其中datas和binaries注意,这是一个键值对,可以枚举一个或多个。
其中,前边的表示拷贝的文件,第二个表示拷贝的路径。

#注意,必须有'.'。否则报错:ValueError: too many values to unpack (expected 2)
#下面这个表示将文件\lib\general.pyc拷贝到当前文件夹下,就是解压的__MIE...等
binaries=[(r'\lib\general.pyc','.')],	#下面表示将\lib\general.xml拷贝到.\data文件夹下
datas=[(r'\lib\general.xml',r'.\data')],#还可以整个文件夹的拷贝,或者一类文件的拷贝。如下设置了多个规则的
datas= [ ('/mygame/sfx/*.mp3', 'sfx' ) ,	#/mygame/sfx/文件夹下所有mp3( '/mygame/data', 'data' ),			#/mygame/data文件夹下所有文件( 'src/README.txt', '.' ),],

上面说了有时候我们需要另外添加资源文件,可以通过编辑spec文件,也可以通过命令行参数。

例如使用opencv的时候存在找不到视频编解码器的情况(Pyinstaller详细教程)
即找不到opencv_ffmpeg341_64.dll
这时候需要我们手动设置资源路径,

可以通过–add-binary参数设置,也可以在spec文件添加binaries参数,这个参数是个list,每个元素是个二元组

binaries=[('D:\\ProgramSourceCode\\PycharmProjects\\video_proc\\venv\\Lib\\site-packages\\cv2\\opencv_ffmpeg341_64.dll', './cv2')]

前一个代表原始资源路径,后一个代表拷贝到可执行文件夹的文件路径。

1.2 是否变成一个exe主文件

来自:https://blog.csdn.net/kevinshift/article/details/104880101

# 打包成一个exe文件
Pyinstaller -F py_word.py 打包exe
# 打包成一个文件夹
Pyinstaller py_word.py 打包exe

pyinstaller打包文件包含两种情况:
(1)将py文件、python及第三方库全部打包为一个单独的Exe中。

(2)将以上三者打包形成一个文件夹,文件夹中包含一个Exe,一个python,及其依赖的第三方库。
二者通过不同的选项
二者的优劣对比:
(a)启动时间
单一可执行文件比文件夹的启动时间要长
因为当程序运行时,单一的可执行文件需要解压程序的第三方依赖文件到临时文件夹中。
(b)文件结构
单一可执行文件的文件结构和工程目录是一样的,但是生成文件夹就不一样了,若程序中包含相对路径,这个相对路径自然基于的是文件夹目录,这点需要注意。
在打包过程出现问题时,可以生成文件结构,进入细致查看发生了什么。

2 虚拟环境打包

按照极简版,其可能会将你所有依赖打包,就会让文件变得非常大。
可以使用conda的虚拟环境

#创建虚拟环境
conda create -n aotu python=3.6#激活虚拟环境
conda activate aotu# 安装必要的依赖pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-docx
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyinstaller#Pyinstaller打包
Pyinstaller -F -w -i apple.ico py_word.py

安装完之后,可以在自己的虚拟镜像里面python x.py试一下是否可以正常执行,就可以开始Pyinstaller 打包


3 其他打包需求

3.1 加密打包

加密打包
来自: https://zhuanlan.zhihu.com/p/470301078
虽然被如此轻松的解密手段😰到了,但是Pyinstaller也是支持加密打包的,使用 --key + 密码 参数即可,例如:

pyinstaller --key 666777 xxx.py

不过这个加密也不是很强,对保密性有很强要求的建议使用把需要加密的模块通过C或者C++编写,通过python调用,再打包。

3.2 Pyinstaller打包多个py文件为一个exe文件

来自:https://blog.csdn.net/weixin_43804047/article/details/119704965

建议将所有的非py脚本放在根目录下新建文件夹中去调用,所有的py脚本放在根目录下

project
|---- test.py
|---- func1.py
|---- func2.py
|---- dir|------ file# test.py为你要封装的文件,func1.py和func2.py为test.py需要调用的py脚本,dir中的文件为py脚本需要调用的非py类文件

你需要这样运行即可:

$ cd project
$ conda activate your_env
$ pyinstaller -w -D test.py func-1.py func-2.py
# 最新测试
# pyinstaller -w -D test.py 也可以

4 如何反编译

来自: https://zhuanlan.zhihu.com/p/470301078
先下载pyinstxtractor包,提取生成的exe中的pyz(一般是pyc)文件

# 安装:直接执行下载的 py 文件即可
# 解包 xx.exe
python pyinstxtractor.py xx.exe

然后再通过python-uncompyle6工具,将pyc文件反编成.py文件

# 安装 
pip install uncompyle6
# 反编译 xxx.pyc 文件,输出为 xxx.py 源码文件
uncompyle6 -o xxx.py xxx.pyc

5 一些报错

5.1 utf-8’ codec can’t decode byte 0xce in position

来着:https://zhuanlan.zhihu.com/p/470301078

utf-8' codec can't decode byte 0xce in position

这是由于cmd的编码格式导致的。
各种路径错误导致的问题
很多人在拼接路径的时候喜欢使用+来拼接路径字符串,这会导致在打包后出现各种资源无法访问的错误,且不好排查,建议多使用os.path的各种方法来处理路径。

5.2 exe文件要从dist文件拿出来

被调用的脚本需要拷贝到dist中打包好的文件夹中,否则可能导致调用失败

project
|---- test.py
|---- func1.py
|---- func2.py
|---- dir|------ fileinput

比如你代码里是直接用./input文件夹,那就要放在跟input平级的文件夹上

5.3 windows打包会将所有之前的依赖统统整上

windows建议使用新建虚拟环境进行打包,新建的envs中只install你的python脚本中import的包即可,这样打包文件很小。笔者做了测试,使用你本来的虚拟环境会把原来的包都打在一块,有300M左右,而新建的envs打包只有50M;Linux系统可以随意安装python库,封装的时候会按照python导入的包去封装,不会将环境内所有package打包。

5.4 pyinstaller的版本一定要保证最新

pyinstaller的版本一定要保证最新,否则运行exe后,小黑框还是原样,什么也不显示,但是拖入cmd中debug是没毛病的。笔者就被这个坑了好久才弄明白。

5.5 A RecursionError (maximum recursion depth exceeded) occurred

Explanation: Python's stack-limit is a safety-belt against endless recursion,
eating up memory. PyInstaller imports modules recursively. If the structure
how modules are imported within your program is awkward, this leads to the
nesting being too deep and hitting Python's stack-limit.With the default recursion limit (1000), the recursion error occurs at about
115 nested imported, with limit 2000 at about 240, with limit 5000 at about
660.

参考:使用pyinstaller打包pyqt5报With the default recursion limit (1000)

当支行过一次pyinstaller后此时运行过的目录下会有一个与要打包的.py文件同名的.spec文件
打开*.spec文件在文件头添加两行代码:

import sys
sys.setrecursionlimit(2000)

之后通过以下方式继续打包:

pyinstaller -D *.spec

5.6 模块找不到的问题解决办法

参考:使用pyinstaller将python程序打包成exe执行文件时遇到模块找不到的问题

在这里插入图片描述
解决办法是:打包时加入你自编模块(或第三方模块所在文件夹路径),笔者程序中调用了shiyanshi自编模块,在D:\Pycharm\Program路径下。

因此打包时需要添加路径进行打包。

使用pyinstaller ***.py -F -p D:\Pycharm\Program
命令在主程序所在文件目录下进行打包,即可解决模块找不到的问题。

在这里插入图片描述


参考:
Python脚本打包成exe,看这一篇就够了!

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

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

相关文章

算法基础之滑动窗口

滑动窗口 主要思想&#xff1a;单调队列 保证队列中下标跨度始终为3个数 q[N]维护数组中元素下标 方便判断窗口大小 #include<iostream>#include<algorithm>using namespace std;const int N1000010;int a[N],q[N];int n,k,hh,tt-1;int main(){cin>>n>…

【C】内存函数

目录 1. memcpy 使用和模拟实现 2. memmove 使⽤和模拟实现 3. memset 函数的使用 4. memcmp 函数的使用 1. memcpy 使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数memcpy从source的位置开始向后复制num个字节的数据到d…

033.Python面向对象_类补充_生命周期

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

Co-DETR:DETRs与协同混合分配训练代码学习笔记

关于论文的学习笔记&#xff1a;Co-DETR:DETRs与协同混合分配训练论文学习笔记-CSDN博客 作者提出了一种新的协同混合任务训练方案&#xff0c;即Co-DETR&#xff0c;以从多种标签分配方式中学习更高效的基于detr的检测器。这种新的训练方案通过训练ATSS和Faster RCNN等一对多标…

Node.js入门指南(四)

目录 express框架 express介绍 express使用 express路由 express 响应设置 中间件 路由模块化 EJS 模板引擎 express-generator hello&#xff0c;大家好&#xff01;上一篇文章我们介绍了Node.js的模块化以及包管理工具等知识&#xff0c;这篇文章主要给大家分享Nod…

C语言进阶之路-运算符小怪篇

目录 一、学习目标 二、运算符详谈 算术运算符 关系运算符 逻辑运算符 位运算符 特殊运算符 条件运算符 sizeof 运算符 打怪实战 三、控制流 二路分支 多路分支 const while与 do…while循环 语法&#xff1a; for循环 break与continue goto语句&#xff08…

输出后,我悟了!

大家好&#xff0c;我是木川 今天和前同事吃饭聊天&#xff0c;谈到了输出&#xff0c;今天简单谈下关于输出的重要性 一、为什么要输出 1、不输出容易忘&#xff0c;如果不输出很容易就忘记了&#xff0c;如果再遇见一次&#xff0c;还是需要重新学习&#xff0c;实际上是浪费…

Windows系统管理之备份与恢复

本章目录&#xff1a; 一. 本章须知&#xff1a; 前置条件 需要创建一个新的磁盘 前置条件2 给新添加的磁盘分盘 二. 了解开启并学会使用Windows sever backup 如何使用备份与恢复“备份计划”“一次性备份”“恢复” 最后是用命令行“一次性备份命令 ”完成一次备份 话不多说 …

【2023传智杯】第六届传智杯程序设计挑战赛AB组-ABC题解题分析详解【JavaPythonC++解题笔记】

本文仅为第六届传智杯程序设计挑战赛-题目解题分析详解的解题个人笔记,个人解题分析记录。 本文包含:第六届传智杯程序设计挑战赛题目、解题思路分析、解题代码、解题代码详解 文章目录 一.前言二.比赛题目(AB俩组)A题题目B题题目C题题目三.解题代码A题解题思路解题代码【J…

Unity 场景切换

Unity场景切换可使用以下方法&#xff1a; 1、SceneManager.LoadScene()方法&#xff1a; using UnityEngine.SceneManagement;// 切换到Scene2场景 SceneManager.LoadScene("Scene2"); 2、使用SceneManager.LoadSceneAsync()方法异步加载场景&#xff0c;异步加载…

Linux:docker基础操作(3)

docker的介绍 Linux&#xff1a;Docker的介绍&#xff08;1&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/134146721?spm1001.2014.3001.5502 通过yum安装docker Linux&#xff1a;Docker-yum安装&#xff08;2&#xff09;-CSDN博客https://blog.…

pandas根据列正逆序排序

题目&#xff1a;根据 buy_quantity 列进行排名&#xff0c;相同值分配相同的最低排名。 import pandas as pd# 创建一个示例 DataFrame data {item_id: [1, 2, 3, 4, 5, 6, 7], buy_quantity: [1, 2, 2, 3, 3, 4, 5]} df pd.DataFrame(data)# 使用 rank() 函数为 buy_quant…