总结Pyinstaller打包的高级用法

一、安装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

二、打包初体验

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

# 测试.py
import os

path = 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图标,又或者去掉命令行窗口呢?

三、打包进阶体验

好了,接下来,我们先看看关于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界面,命令行窗口并没有出现。

四、带配置文件打包

所谓带配置文件打包,这里是指打包的时候除了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模块,那么这是什么情况呢?!

五、添加隐式调用库

我们找到报错的地方代码如下,采用了__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

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

方案一:在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终于成功打包且正常运行使用了。

以上就是本次全部内容,大家如果遇到打包时涉及到配置文件的或者隐式调用的,可以采用这两个2技巧进行特殊打包!

不过,关于pyinstaller打包其实还有更多操作,大家可以多看看官方文档了解,主要是命令行参数spec文件里的配置要点

到此这篇关于总结Pyinstaller打包的高级用法的文章就介绍到这了,更多相关Pyinstaller打包内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python 利用Pyinstaller打包Web项目

    最近需要用python打包一个单页面网页demo,于是准备用python包pyinstaller来打包程序.网上搜索了一下,大部分教程都是打包非web项目,这里分享一下打包简单网页demo的过程. 系统环境:win10+python3.6 一.安装pyinstaller pip install pyinstaller 二.打包项目 1.如果是单文件项目,pyinstaller可以通过简单的命令进行python代码的打包工作,其命令为: pyinstaller -option ***.py 1.1

  • 简单介绍一下pyinstaller打包以及安全性的实现

    pyinstaller打包问题 简单介绍一下pyinstaller常用的参数: 可选参数 示例 说明 -F pyinstaller -F demo.py 只在dist文件夹中生成一个程序demo.exe文件,适用于一个模块没有多依赖.py文件 -D pyinstaller -D demo.py 默认选项,除了主程序demo.exe外,还会在在dist文件夹中生成很多依赖文件,推荐使用这个 -c pyinstaller -c demo.py 默认选项,只对windows有效,使用控制台 -w py

  • Pyinstaller打包文件太大的解决方案

    废话不多说 原因: 在Anaconda下打包的很多不必要的模块进去,导致最终的exe文件过于庞大. 解决办法: 要用纯净的python来打包即可避免加入不必要的包,那么如何快速地建立纯净的python环境呢? 当然不用重装python,只需要通过pipenv建立虚拟环境即可.在虚拟环境下打包,最终的exe文件会非常小(几M). #第一步,建立虚拟环境 pipenv install #第二步,进入虚拟环境 pipenv shell #第三步,安装自己最终打包的py文件下需要的模块即可 pip in

  • 教你使用pyinstaller打包Python教程

    一.单个文件打包 1.1 简单打包 例如现在有一个main.py文件内容如下 import os print("hello world") os.system("pause") 运行结果如图 现在用一下命令打包成一个可执行文件pyinstaller -F main.py 再同级目录下生成一个dist文件夹里面就会生成一个可执行文件,双击就可以执行 1.2 带图标打包 有的时候为了美观,可以给可执行文件加一个图标,这时用这个命令pyinstaller -F main.

  • 总结Pyinstaller打包的高级用法

    一.安装pyinstaller PyInstaller是一个用来将Python程序打包成一个独立可执行文件的第三方包. 因是第三方包,所以需要安装一下: pip install pyinstaller 或者升级到最新版本: pip install --upgrade pyinstaller 或者安装开发者版本: pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz 当然了,也可以下载whl文件,

  • 基于Pyinstaller打包Python程序并压缩文件大小

    这段时间应老师的要求,给实验室写了一个基于 PyQt5 的小工具.然而源码发过去人家还不要,一定要打包成可执行软件. 那就打包呗,刚好以前对 Pyinstaller 有一点接触,就用了一下这玩意.这篇博文主要记录一下基本用法和踩得一些坑. 1. 用 Pyinstaller 打包 Python 程序 首先我们需要安装 Pyinstaller: pip install pyinstaller 用 conda 也行,不过貌似最近清华的 Anaconda 源被封了,也不知道什么时候解禁. Pyinsta

  • Java SpringBoot高级用法详解

    目录 1,IDEA中Lombok作用 创建项目 2.pom.xml说明 2.1 pom.xml标签说明 2.2 依赖的相关说明 2.3 SHA1介绍 SpringBoot高级用法 YML文件说明 3.需求说明 3.2利用properties文件为属性赋值 总结 1,IDEA中Lombok作用 数据库: 库 表 字段 对应的值 user表(id,name,age) 实体对象pojo: 用来封装数据库中的数据 User类(id,name,age) 实体对象方法: Get/Set/toString/无

  • AngularJS中下拉框的高级用法示例

    本文实例讲述了AngularJS中下拉框的高级用法.分享给大家供大家参考,具体如下: HTML正文: <body ng-app="myApp"> <!-- 对象内部属性遍历:x--key y---value --> <div ng-controller="myctr01"> {{sites}}<br> <select ng-model="site" ng-options="x for

  • PHP的switch判断语句的“高级”用法详解

    只所以称为"高级"用法,是因为我连switch的最基础的用法都还没有掌握,so,接下来讲的其实还是它的基础用法! switch 语句和具有同样表达式的一系列的 IF 语句相似.很多场合下需要把同一个变量(或表达式)与很多不同的值比较,并根据它等于哪个值来执行不同的代码.这正是 switch 语句的用途. 注意: 注意和其它语言不同,continue 语句作用到 switch 上的作用类似于 break.如果在循环中有一个 switch 并希望 continue 到外层循环中的下一个轮回

  • asp.net core标签助手的高级用法TagHelper+Form

    上一篇博客我讲解了TagHelper的基本用法和自定义标签的生成,那么我就趁热打铁,和大家分享一下TagHelper的高级用法~~,大家也可以在我的博客下随意留言. 对于初步接触asp.net core的骚年可以看看我对TagHelper的了解和看法: <asp.net core新特性(1):TagHelper> 之后,我也会继续撰写博文,继续分享asp.net core的一些新特性,比如DI,ViewComponent以及bower等asp.net mvc中没有的新东西. ok,咱们就开始吧

  • Android自定义view Path 的高级用法之搜索按钮动画

    关于Path之前写的也很多了,例如path绘制线,path绘制一阶,二阶和三阶贝塞尔路径,这些都是path的基本用法.今天我要带大家看的是Path 的高级用法,先上图,再吹. 效果大致是这样的.看着是不是挺好.话不多说,切入正题: 既然今天要谈Path的高级用法,那就先来讲一讲(Path -- 中文 )就是"路径"既然是路径,从我们面向对象的想法的话,我们就容易想到 路径 的长度,路径的某一点等.想到这里我们就引出今天 的主要 类--------PathMeasure,字面意思很容易理

  • 浅谈junit4单元测试高级用法

    Junit单元测试框架是Java程序开发必备的测试利器,现在最常用的就是Junit4了,在Junit4中所有的测试用例都使用了注解的形式,这比Junit3更加灵活与方便.之前在公司的关于单元测试的培训课程中,讲师仅仅讲述了Junit4的基本的与生命周期相关的注解的使用,主要包括@BeforeClass.@Before.@Test.@After.@AfterClass这些注解,这些在应付普通简单的单元测试已经足够,然而有很多更加复杂且也会经常遇到的测试需求依靠这些生命周期注解并不能完成!因此这篇分

  • Python tkinter事件高级用法实例

    本文实例讲述了Python tkinter事件高级用法.分享给大家供大家参考,具体如下: 先来看看运行效果: 完整实例代码: # -*- coding:utf-8-*- #! python3 from tkinter import * import threading, time trace = 0 class CanvasEventsDemo: def __init__(self, parent=None): canvas = Canvas(width=300, height=300, bg=

随机推荐