python利用pyinstaller打包简明教程

pyinstaller简明教程

安装pyinstaller

pip install pyinstaller是最简单的安装方式,但也常常由于各种原因报错,这就需要我们通过whl文件来下载,但是whl文件安装也有考究,具体参考我之前的教程:Python安装whl文件那些坑,下载whl一般可以在whl文件仓库中找到,如果找不到就去第三方库的官网下载,我个人比较倾向于第二种。

这是我最后一次阐述pip install的问题,后续的教程都不再赘述

pyinstaller基本用法

假如我们要打包一个demo.py文件,基本过程是:

打开cmd,并切换到demo.py文件所在的目录,注意路径中不要有中文
执行命令:pyinstaller demo.py
在当前的目录下,将会生成两个文件夹:build和dist。dist里面就是所有可执行文件,点击demo.exe就能运行了。

pyinstaller指令的常见可选参数:

可选参数 格式举例 功能说明
-F pyinstaller -F demo.py 只在dist中生产一个demo.exe文件。
-D pyinstaller -D demo.py 默认选项,除了demo.exe外,还会在在dist中生成很多依赖文件,推荐使用。
-c pyinstaller -c demo.py 默认选项,只对windows有效,使用控制台,就像编译运行C程序后的黑色弹窗。
-w pyinstaller -w demo.py 只对windows有效,不使用控制台。
-p pyinstaller -p E:\python\Lib\site-packages demo.py 设置导入路径,一般用不到。
-i pyinstaller -i D:\file.icon demo.py 将file.icon设置为exe文件的图标,推荐一个icon网站:icon
-n pyinstaller -n 我的gui demo.py exe的命名为什么

上面的可选参数可以组合使用,比如pyinstaller -F -i D:\file.icon demo.py
能够from xxx import yyy就尽量不要import xxx,这样可以减少打包后的体积。

pyinstaller高阶功法

一般而言,pyinstaller的基本用法已经够用了,但是有特殊需求,比如打包图片资源文件时,就必须用到它的高阶功法了。

首先得了解spec文件,简而言之,spec文件就是一份告诉pyinstaller如何打包的配置文件。
可以通过pyi-makespec demo.py来生成demo.spec文件。其内容如下:

# -*- mode: python -*-

block_cipher = None

resources = (("inspurer.db", "."), ("dlib_face_recognition_resnet_model_v1.dat", "."),
 ("shape_predictor_68_face_landmarks.dat", "."), ("close_logcat.png", ".")
 , ("open_logcat.png", "."), ("finish_register.png", "."), ("new_register.png", ".")
 , ("start_punchcard.png", "."), ("end_puncard.png", "."), ("index.png", "."))

a = Analysis(['workAttendanceSystem.py'],
             pathex=['C:\\Users\\lenovo\\Desktop\\test\\python'],
             binaries=[],
             datas=resources,
             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,
          [],
          exclude_binaries=True,
          name='workAttendanceSystem',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='workAttendanceSystem')

对于上面这个文件,需要注意两点:

除了resources配置是我添加修改之外,其余全是自动生成,这个配置是用来添加资源文件的。
pathex是工程的根目录。

生成并配置好spec文件后,我们可以通过pyinstaller demo.spec来执行打包任务。

一点经验

pyinstaller打包的exe体积往往都非常巨大,而且打包过程非常耗时,和C/C++编译的exe目测差了几个数量级,所以一般没有这个必要去把一个大的python工程打包成exe可执行文件。我想这也是未来python如果想要成为大型软件开发工程的热门语言所要克服的一个重大缺点吧。

常见问题

1.路径问题

  • 多文件打包,不会报错。

  • 单文件打包,报错。

    为什么会报错?加载&解析到临时目录问题。
    
1.1 sys.argv

路径的使用:

# BASE_PATH = os.path.dirname(os.path.abspath(__file__))
BASE_PATH = "."
BASE_PATH = os.path.dirname(os.path.realpath(sys.argv[0]))
1.2 frozen

官方提供的方法:

import sys
if getattr(sys, 'frozen', False): # True
    print('running in a PyInstaller bundle')
else: # False
    print('running in a normal Python process')
import time
import os
import sys

if getattr(sys, 'frozen', False):
    # pyinstaller打开
    BASE_DIR = os.path.dirname(sys.executable)
else:
    # py文件路径
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))

print("----环境使用xxx系统----")

with open(os.path.join(BASE_DIR, "account.txt"), mode='r', encoding='utf-8') as f:
    data = f.read().strip()
print(data)

time.sleep(5)

2. 模块导入的问题

正常导入,通常是可以正常打包的,注意要把当前目录的__init__.py删除

from utils import card

如果遇到那种动态导入模块的代码时,他是无法找到关联的包。

import time
import importlib

print("----环境使用xxx系统----")

# from utils import card
# card.get_number()

card = importlib.import_module("utils.card")
v1 = card.get_number()
print(v1)

time.sleep(5)

需要在spec文件中的,Analysis中的隐式导入 hiddenimports 加入 "utils.card"

posted @ 2020-04-01 16:21  hanfe1  阅读(742)  评论(0)    收藏  举报