Pyinstaller打包高级用法

2023-05-16

前段时间在制作词云制作小工具的时候,直接在命令行用pyinstaller -F 工具.py指令打包成功后,启动exe可执行文件的时候各种报错。

今天,我们就分享一下踩坑经过。

目录:

  • 1. 安装pyinstaller

  • 2. 打包初体验

  • 3. 打包进阶体验

  • 4. 带配置文件打包(高级)

  • 5. 添加隐式调用库(高级)

1. 安装pyinstaller


PyInstaller是一个用来将Python程序打包成一个独立可执行文件的第三方包。

因是第三方包,所以需要安装一下:

pip install pyinstaller

或者升级到最新版本:

pip install --upgrade pyinstaller

或者安装开发者版本:

pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz

当然了,也可以下载whl文件,然后pip install安装

更多可参考官网指引:

http://www.pyinstaller.org/downloads.html

2. 打包初体验


我们简单试下打包python代码为exe可执行文件,测试代码如下:

# 测试.pyimport ospath = os.getcwd()print(f'当前文件路径:{path}')os.system('pause')

这段代码是打印文件所在的目录,我们用pyinstaller简单打包的命令如下:

pyinstaller -F 测试.py

这个命令,执行过程如下:

(env_test) F:\PythonCool\pyinstaller>pyinstaller -F 测试.py    
403 INFO: PyInstaller: 4.3
403 INFO: Python: 3.8.10 (conda)
434 INFO: Platform: Windows-10-10.0.19042-SP0
436 INFO: wrote F:\PythonCool\pyinstaller\测试.spec
455 INFO: UPX is not available.
468 INFO: Extending PYTHONPATH with paths
['F:\\PythonCool\\pyinstaller', 'F:\\PythonCool\\pyinstaller']
501 INFO: checking Analysis
...
...
15006 INFO: Appending archive to EXE F:\PythonCool\pyinstaller\dist\测试.exe
18999 INFO: Building EXE from EXE-00.toc completed successfully.

成功后会在同级目录下生成一个dist文件,里面就是一个和代码文件名同名的可执行文件:

双击该可执行文件,我们可以看到直接在python解释器里运行测试.py文件时一样的结果:

这里需要注意的是,我们在进行打包的时候,有必要指定被打包的py文件的路径,两种方式供选择:

方式一:先切换到被打包py文件目录,再执行打包指令

(base) C:\Users\Gdc>cd F:\PythonCool\pyinstaller
(base) C:\Users\Gdc>F:
(base) F:\PythonCool\pyinstaller>pyinstaller -F 测试.py

方式二:打包指令中指定py文件的绝对路径

(base) C:\Users\Gdc>pyinstaller -F F:\PythonCool\pyinstaller\测试.py

关于成功打包的测试.exe可执行文件,我们发现其图标是默认的,且启动时会显示命令行窗口。那么,我们可以怎么自定义exe图标,又或者去掉命令行窗口呢?

3. 打包进阶体验


好了,接下来,我们先看看关于pyinstaller打包时候的一些别的参数都有哪些,如何自定义exe图标以及如何去掉命令行窗口等等。

(env_test) F:\PythonCool\pyinstaller>pyinstaller -h

pyinstaller -h可以查看其参数说明,由于较多这里不做完整展示,摘取部分常用参数做简要介绍:

参数

说明

-F

产生单个的可执行文件

-D

产生一个目录(包含多个文件)作为可执行程序

-a

不包含 Unicode 字符集支持

-d

debug 版本的可执行文件

-w

指定程序运行时不显示命令行窗口(仅对 Windows 有效)

-c

指定使用命令行窗口运行程序(仅对 Windows 有效)

-o

指定 spec 文件的生成目录。如果没有指定,则默认使用当前目录来生成 spec 文件

-p

设置 Python 导入模块的路径(和设置 PYTHONPATH 环境变量的作用相似)。也可使用路径分隔符(Windows 使用分号,Linux 使用冒号)来分隔多个路径

-n

指定项目(产生的 spec)名字。如果省略该选项,那么第一个脚本的主文件名将作为 spec 的名字

打包一个带自定义icon的exe可执行文件

我们可以去这里下载icon文件:

https://www.iconfont.cn/

可以去这里将图片转化为icon文件:

https://www.bitbug.net/

然后,用一下命令可以自定义exe图标:

(env_test) F:\PythonCool\pyinstaller>pyinstaller -F -i icon.ico 测试.py 

成功后,我们可以看到图标变成了我们自定义的这个:

打包去掉命令行弹窗的exe可执行文件

如果我们是有GUI的程序,想在启动的时候去掉命令行窗口,那么可以用以下指令进行打包,这里以tkinter内置GUI库为例展示:

# 测试.py
import tkinter

top = tkinter.Tk()
# 进入消息循环
top.mainloop()

以上测试代码,如果用初体验中的方式,在GUI界面出现的同时也会出现命令行弹窗,我们想去掉命令行弹窗可以:

(env_test) F:\PythonCool\pyinstaller>pyinstaller -F -w -i icon.ico 测试.py  

双击打包后的exe文件,可以看到只会出现GUI界面,命令行窗口并没有出现。

4. 带配置文件打包


所谓带配置文件打包,这里是指打包的时候除了py文件、依赖的库之外,还存在需要引用的其他资源文件。直接用以上方式打包的时候,这些资源是无法被打进包的,我们需要进行修改打包时的spec文件来实现。

spec文件是告诉Pyinstaller怎么打包py文件,比如路径、资源、动态库、隐式调用的模块等等。一般来说,我们不需要对它进行修改...

这里我用此前《词云绘制小工具》的案例来进行介绍。

我们直接用打包进阶体验中的命令可以进行成功打包,不过这里我们发现有两个问题:①包体很大,比此前案例里大了10倍左右;②启动exe文件的时候报错了。

关于包体较大的情况,可以试着创建虚拟环境,然后只安装程序里需要调用的库即可,这里只简单介绍:

# 创建虚拟环境
conda create -n your_env_name python=3.8.10
# 启动虚拟环境
activate your_env_name

关于启动报错的情况,由于比较复杂,我们一步一步来看:

由于无命令行弹窗,无法查看到具体的报错,这里先去带命令行窗口形式看下报错信息,我们看报错如下:

提示缺少这个文件,我们可以在打包生成的词云绘制工具.spec配置文件里将这个资源放上

# -*- mode: python ; coding: utf-8 -*-
# 词云绘制工具.spec

block_cipher = None

a = Analysis(['词云绘制工具.py'],
             pathex=['F:\\PythonCool\\pyinstaller'],
             binaries=[],
             datas=[], # 这里带上资源文件地址
             hiddenimports=[], # 动态引入的库或模块
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='词云绘制工具',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True , icon='icon.ico')

通过在wordcloud模块目录里查到了stopwords文件,我们将其放到data中。

datas=[('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\wordcloud\\stopwords','wordcloud')], # 这里带上资源文件地址

前者是资源文件在本机的位置,后者为打包后文件调用的相对路径,编辑好spec文件后,通过以下命令进行打包:

(env_test) F:\PythonCool\pyinstaller>pyinstaller -D 词云绘制工具.spec  

好吧,还有一些文件未被打进包,所以又出现同样的问题了。所以,我们是需要把全部的资源文件都加到spec文件里的data中。

我们找到全部的资源文件全部加上吧,然后再执行打包命令。

datas=[('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\stylecloud\\static','stylecloud\\static'),    ('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\wordcloud\\stopwords','wordcloud'),    ('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\jieba\\analyse\\idf.txt','jieba\\analyse'),    ('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\jieba\\dict.txt','jieba')]

我们将配置资源打进包后可以正常启动exe可执行文件了。

但是,又发现在执行词云绘制的时候,也会出现报错。不过看报错的情况是提示不存在xx模块,那么这是什么情况呢?!

5. 添加隐式调用库


我们找到报错的地方代码如下,采用了__import__()函数用于动态加载类和函数palettable模块。

def gen_palette(palette: str):
    """Generates the corresponding palette function from `palettable`."""
    palette_split = palette.split(".")
    palette_name = palette_split[-1]

    # https://stackoverflow.com/a/6677505
    palette_func = getattr(
        __import__(
            "palettable.{}".format(".".join(palette_split[:-1])),
            fromlist=[palette_name],
        ),
        palette_name,
    )
    return palette_func

对于这个问题,我试过三种方案,大家可以参考一下。

方案一:使用--hidden-import参数进行打包

pyinstaller -D 词云绘制工具.spec --hidden-import palettable

方案一:在spec文件中hiddenimports中添加动态引用的模块

hiddenimports=['palettable'], # 动态引入的库或模块

这种情况下,palettable库里也有一些配置文件需要添加到spec文件里的data中

('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\palettable\\colorbrewer\\data','palettable\\colorbrewer\\data')

方案二:修改stylecloud库中调用palettable模块的代码部分

import palettable
def gen_palette(palette: str):
    palette_func = getattr(palettable.tableau,'BlueRed_6')
    return palette_func
 
    # """Generates the corresponding palette function from `palettable`."""
    # palette_split = palette.split(".")
    # palette_name = palette_split[-1]

    #    https://stackoverflow.com/a/6677505
    # palette_func = getattr(
        # __import__(
            # "palettable.{}".format(".".join(palette_split[:-1])),
            # fromlist=[palette_name],
        # ),
        # palette_name,
    # )

通过第4和5部分,我们用pyinstaller终于成功打包且正常运行使用了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pyinstaller打包高级用法 的相关文章

随机推荐

  • centos相关软件下载地址

    CentOS7 6 下载地址 CentOS 7 x86 64 DVD 1810 iso CentOS 7 6 DVD 版 4G http mirrors 163 com centos 7 6 1810 isos x86 64 CentOS
  • C++笔记(《C++新经典》)

    C 43 43 新经典 第1章 C C 43 43 1 1 C和C 43 43 语言的起源 特点 关系与讲解范畴1 2 C C 43 43 语言市场需求与就业需求分析1 3 再谈C C 43 43 就业1 4 搭建开发语言环境 第2章 数据
  • FileZilla连接ubuntu

    我新搭建了一个ubuntu 1 查看ssh的状态 xff1a sudo service sshd status 如果出现 xff1a ssh span class token punctuation span service span cl
  • office2016 excel复制粘贴就卡死

    原因 可能和这个帐户的缓存有关系 xff0c 或第三方软件有关系 xff0c 1 xff1a 重新安装office无效 2 xff1a 按照微软 xff0c 点文件 选项 com加载项 把里面复选框都去掉 xff0c 均无效 网上好多类似文
  • 路虽远,行则将至;事虽难,做则必成。

    新年第一天 xff0c 以奋斗为起点
  • Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build Tools“的解决办法

    在Windows系统上使用pip安装一些软件时 xff0c 会出现下面这样的问题 error Microsoft Visual C 43 43 14 0 or greater is required Get it with Microsof
  • tp5 A non-numeric value encountered解决方法

    报错信息如下 解决方法 xff1a 在对应的控制器方法加入下面这行代码即可 ini set 34 error reporting 34 34 E ALL amp E NOTICE 34
  • 自学Python day05-for循环

    语法 for 临时变量 in 序列名 xff1a xxxx 序列的意思是 xff0c 一个数据是由多个数据组成的 xff0c 例如列表 xff1a 1 2 xff0c 3 xff0c 3 xff0c 4 5 xff0c 6 7 xff0c
  • 并查集--解析关押罪犯问题(二)

    在网上看到一道ACM竞赛题 xff0c 很巧妙的运用了并查集解决了一个现实生活的问题 xff0c 然而网上的解析太少 xff0c 在这里贴出来我的思考 xff1a 题目 xff1a S 城现有两座监狱 xff0c 一共关押着N 名罪犯 xf
  • 如何在Windows下安装ubuntu子系统

    TOCM 如何在Windows下安装ubuntu子系统 1 windows设置 首先打开控制面板 xff0c Windows设置 xff0c 勾选Windows下的linux系统 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直
  • R语言批量生成CaseWhen的解决方案

    近期写R代码 xff0c 经常用dplyr case when结合stringr str detect进行条件判断 痛点 xff1a 判断条件可能会改或增删 xff0c 全写在case when里 xff0c 代码冗余且不利于复制和维护 x
  • R新管道操作符 |> 使用体验

    R users应该对magrittr的 gt 管道符都不陌生 然后R官方估计看如此普及不能再装看不见了 xff0c 于是4 1版本官方也出了个管道操作符 gt xff0c 简直就是baseR党的福音啊 虽然我不是忠实的baseR党 xff0
  • R包bs4Dash控件效果对照图

    记录一下bs4Dash各个控件的效果 xff0c 方便查找和对照 案例均来自于官方文档 accordion accordion span class token punctuation span id span class token op
  • 用一个公式列出R语言所有的数据集

    做了个app xff0c 点R datasets快速查看数据集 测试数据 xff0c 经常用到R语言的数据集 xff0c 于是就开始寻思怎么用尽可能短的代码把所有的数据集一次性全列出来 xff0c 再慢慢挑选 代码如下 xff1a data
  • R语言用dbplyr操作数据库解决丢失连接以持久化tbl查询的方案

    在我看来 xff0c R语言tidyverse包里 xff0c 最高价值的包是dbplyr xff08 dplyr的数据库版 xff09 xff0c 用起来非常爽 xff0c 但最怕的是丢失数据库连接 xff0c 一丢则流畅感瞬间崩塌 xf
  • iPad使用UTM SE装Win7

    因工作需要 xff0c 有的公文只能在windows系统下才能通过vpn及专用控件情况下审批 xff0c 带个电脑嫌笨重 xff0c 经测试 xff0c 在ipad上通过虚拟机成功安装win7系统 xff0c 当然还可以安装linux ma
  • Excel内置函数参数为整列是否会有性能损失

    比如 xff0c sumif a a b c c 的性能是否会比限定范围的公式sumif a1 a10 b c1 c10 的性能更差 答案是 xff0c 不会 看微软官方的回答 所以 xff0c 放心大胆的用sumif 43 entire
  • 远程代码执行(RCE)漏洞

    文章目录 1 fastjson 远程代码执行漏洞2 简单复现3 反弹shell3 1 正向反弹shell3 2 反向反弹shell 1 fastjson 远程代码执行漏洞 最近读到一篇文章 fastjson 远程代码执行漏洞分析 xff0c
  • 洛谷 P4180 【模板】严格次小生成树

    题目链接 https www luogu org problem P4180 分析 根据Kruskal算法的思想 xff0c xff08 非 xff09 严格次小生成树应该是来自最小生成树的 xff1b 具体来说 xff0c 是将某条非树边
  • Pyinstaller打包高级用法

    前段时间在制作词云制作小工具的时候 xff0c 直接在命令行用pyinstaller F 工具 py指令打包成功后 xff0c 启动exe可执行文件的时候各种报错 今天 xff0c 我们就分享一下踩坑经过 目录 xff1a 1 安装pyin