文章目录

  • 一、描述
  • 安装
  • 资料
  • 二、打包配置
  • 控制台
  • spec规范文文件
  • 三、入门
  • 常用参数
  • One-Folder模式和One-File模式
  • 调出控制台窗口与否
  • add-data
  • 三、进阶
  • execute多个文件
  • 自定义模块的no module问题
  • python库no module的问题



一、描述

  • 第三方库,要自己安装。
  • 将Python程序打包成标准的可执行文件,这些文件可以在没有安装Python的计算机上运行。
  • win、linux、mac

安装

pip install pyinstaller

二、打包配置

均等同。

控制台

控制台中:pyinstaller [options] script

pyinstaller my_script.py --onefile --windowed

把控制台中的命令写成python文件让其执行,到时候python 文件.py

import PyInstaller.__main__

PyInstaller.__main__.run([
    'my_script.py',
    '--onefile',
    '--windowed'
])

spec规范文文件

将控制台中的命令写成规范文文件,到时候pyinstaller [options] 规范文文件.spec

PS:从规范文件构建时,命令行中options指定的参数会和规范文件内指定的参数起冲突:

  • 大部分将被忽略,参数只按照规范文件中的选项配置。
  • 只有以下命令行的参数起作用:--upx-dir=--distpath=--workpath=--noconfirm--ascii--clean(▲)。

三、入门

常用参数

参数 options

作用

-h,--help

显示帮助

-v, --version

显示程序版本信息

-n NAME, --name NAME

命名(默认值:第一个脚本的名称)

--clean

清理 PyInstaller cache,在构建之前删除临时文件

-D, --onedir

One-Folder模式(默认)

-F, --onefile

One-File模式

-c, --console, --nowindowed

【win和mac特定】调出控制台窗口(默认)。

-w, --windowed, --noconsole

【win和mac特定】不调出控制台窗口,即静默模式。

-i <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>,

--icon <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>

【win和mac特定】

①FILE.ico:将该图标应用于Windows可执行文件。

②FILE.exe,ID,从exe中提取ID为ID的图标。

③FILE.icns:将图标应用于Mac OS X上的.app捆绑包。

④使用“ NONE”不应用任何图标,从而使操作系统显示某些默认设置。

⑤默认(不写这个参数时):用PyInstaller的图标

--add-data <SRC;DEST or SRC:DEST>

win下用;分隔,是前者;linux下用:分隔,是后者。

SRC是文件打包前所在路径,DEST是在打包程序中的目录安排。

一般是txt、图片、pdf、配置文件之类的

--add-binary <SRC;DEST or SRC:DEST>


一般是dll、so

-p DIR, --paths DIR

One-Folder模式和One-File模式

ubantu python打包 python 打包库_临时文件


打包get.py,产生三个文件(夹):

  • get.spec:用于pyinstaller打包的规格文件。不用关心。
  • build:如同大多数编译器一样的构建过程文件夹。不用关心。
  • dist:结果产物,你关心的。

One-Folder模式:

pyinstaller get.py

这就是那种发过来一个zip文件夹,你解压一下运行其中exe的程序。

正如解压,把这个get文件夹压缩成zip,给别人就行。

单独把exe移出文件夹运行,失败。

ubantu python打包 python 打包库_ico_02


ubantu python打包 python 打包库_ubantu python打包_03

One-File模式:

pyinstaller -F get.py

本质是把那么多文件都整合到了exe中,运行时再解压出来。

运行的时候会解压到临时文件夹,所以运行时启动会因为这个原因慢一点点,之后运行就和One-Floder一样快。

ubantu python打包 python 打包库_临时文件_04

调出控制台窗口与否

  • print()之类的I/O信息会输出到控制台窗口上。
  • 静默模式下,程序该运行的还是会好好运行的。用途可以是,程序不需要你在控制台上输入,你不想看到控制台的输出信息时,静默后台执行的程序。
  • 你有GUI的图形化界面,自然不需要控制台窗口。

add-data

One-Folder

# 3.py
   
import os,sys

with open('hhhhhh.txt', 'r') as fp:
    print(fp.readlines())
pyinstaller --add-data ./hhhhhh.txt:. 3.py

ubantu python打包 python 打包库_ico_05


ubantu python打包 python 打包库_临时文件_06

因为确实存在于目录下,所以直接就能获取

One-File

ubantu python打包 python 打包库_临时文件_07

因为One-File中是解压到临时文件夹中下,而不是当前文件夹下,自然找不到。

所以解决办法就是:使用绝对路径=临时文件夹目录+相对路径。

# 3.py

from os import path
# 主文件解压后的绝对路径
print('__file__=',__file__)
# 主文件解压后所在目录的绝对路径
parentPath = path.dirname(__file__)
print('parentPath=',parentPath)

toolPath = path.dirname(path.join(parentPath,'.'))
print('toolPath=',toolPath)

# 打印看一下path下的各文件、文件夹情况
from os import listdir
for _ in listdir(path):          
    print(_)

# 绝对路径+相对路径
with open(path.join(toolPath,'hhhhhh.txt'),'r') as fp:
    print(fp.readlines())
pyinstaller --add-data ./hhhhhh.txt:.  3.py -F

ubantu python打包 python 打包库_ubantu python打包_08

三、进阶

execute多个文件

# 这样表示你顺序执行多个py文件
pyinstaller [options] script1 script2 …
# 1.py
if __name__ == "__main__":
    print('it is 1.py')
# 2.py
if __name__ == "__main__":
    print('it is 2.py')
pyinstaller 1.py 2.py

ubantu python打包 python 打包库_ubantu python打包_09

打包出来都是以其为主程序来执行。a.pyb.py谁先谁后,只关乎打包文件的名字采用第一个文件,谁先运行罢了。
所以写模块文件的时候,不要在模块文件中写if __name__ == "__main__":的测试部分。

自定义模块的no module问题

因为按照第二种修改sys.path的写法来调用模块b.py,pyinstaller就找不到,你得加入pyinstaller -p=/home/admin/pro/tool模块的目录名,非常麻烦。

而按照这种python 调用其他文件函数或类的“主程序与模块写法”,pyinstaller能轻易找到tool模块,直接pyinstaller a.py就成了。

PS:而且这种写法from tool.b import */import tool.b,pyinstaller看到tool.b,会保留了这种模块文件的结构。

`
|-- a.py
`-- tool
    `-- b.py

而修改sys.path的写法,虽然能运行,但是pyinstaller丢失了这种模块结构,b.pya.py在同一个目录下。

`
|-- a.py
`-- b.py

这个可关乎到模块文件访问资源文件的问题。比如,tool/init.py要访问src/setting.ini,第二步airtest_project的路径就会出现问题。

ubantu python打包 python 打包库_绝对路径_10

# init.py文件中
print('__file__', __file__)			# init.py的路径
pro_dir_path = path.abspath(path.join(path.dirname(__file__), '..'))	# airtest_project的路径
print('pro_dir_path=', pro_dir_path)
setting_path = path.abspath(path.join(pro_dir_path, 'src/setting.ini'))	# airtest_project的路径/src/setting.ini
print('setting_path=', setting_path)

python库no module的问题

pyinstaller并不是支持所有的库的,因为有些库写法很糟糕,它无法识别到。

所以要手动打包进去(使用One-Fold模式)。

ubantu python打包 python 打包库_绝对路径_11


ubantu python打包 python 打包库_临时文件_12

把缺失的库直接复制到这里。

ubantu python打包 python 打包库_ubantu python打包_13


ok。