pyinstaller, cx_Freeze打包 pyqt 桌面应用-实操

1 pyinstaller 打包成 exe

参考这个连接, 写的比较全面: https://blog.csdn.net/qq_48979387/article/details/132359366

唯一发现一个错误是增加资源文件时候的分隔符(-add-data SOURCE:DEST), 按照自己环境的实际的情况来:

$ pyinstaller --help
usage: pyinstaller [-h] [-v] [-D] [-F] [--specpath DIR] [-n NAME] [--contents-directory CONTENTS_DIRECTORY] [--add-data SOURCE:DEST] [--add-binary SOURCE:DEST] [-p DIR] [--hidden-import MODULENAME]      
                   [--collect-submodules MODULENAME] [--collect-data MODULENAME] [--collect-binaries MODULENAME] [--collect-all MODULENAME] [--copy-metadata PACKAGENAME]
                   [--recursive-copy-metadata PACKAGENAME] [--additional-hooks-dir HOOKSPATH] [--runtime-hook RUNTIME_HOOKS] [--exclude-module EXCLUDES] [--splash IMAGE_FILE]
                   [-d {all,imports,bootloader,noarchive}] [--optimize LEVEL] [--python-option PYTHON_OPTION] [-s] [--noupx] [--upx-exclude FILE] [-c] [-w]
                   [--hide-console {hide-early,minimize-late,hide-late,minimize-early}] [-i <FILE.ico or FILE.exe,ID or FILE.icns or Image or "NONE">] [--disable-windowed-traceback] [--version-file FILE]
                   [-m <FILE or XML>] [-r RESOURCE] [--uac-admin] [--uac-uiaccess] [--argv-emulation] [--osx-bundle-identifier BUNDLE_IDENTIFIER] [--target-architecture ARCH]
                   [--codesign-identity IDENTITY] [--osx-entitlements-file FILENAME] [--runtime-tmpdir PATH] [--bootloader-ignore-signals] [--distpath DIR] [--workpath WORKPATH] [-y] [--upx-dir UPX_DIR]    
                   [--clean] [--log-level LEVEL]
                   scriptname [scriptname ...]


如果我们的项目知识纯python 脚本, 没有配置文件, 资源文件等外部依赖, 那么pyinstaller的配置参数相对简洁

pyinstaller -F -w   your_main_script

参数 -F的意思是 将所有的文件(python的脚本和如干依赖文件打包成一个 exe), 如果不加这个参数, 会将程序大包围一个exe文件和一个文件夹(里面包含需要的依赖文件)
参数-w 控制是否显示 console, 加上这个参数表示不显示控制台, 去掉表示显示控制台

下面给我我自己实践的一个过程。 我的项目是利用pyqt做了一个应用界面, 其中包含三个python脚本: 一个主程序外加两个绘制Ui python 脚本, 所需要的图片和数据资源, 具体目录如下:
在这里插入图片描述

上面的参考文件着重说了, 如果脚本涉及到数据文件引用的情况, 要注意目录路径的使用, 因为打包成exe后, 数据目录相对路径会变化的, 所以给出解决方案是:

def get_path(relative_path):
    try:
        base_path = sys._MEIPASS # pyinstaller打包后的路径
    except AttributeError:
        base_path = os.path.abspath(".") # 当前工作目录的路径
 
    return os.path.normpath(os.path.join(base_path, relative_path)) # 返回实际路径

具体使用上, 我的数据文件的引用方式:

            engine_config_path = get_path('./engine_config.json')
            engine_config_path = Path(engine_config_path)

当然我的代码还包含图像文件, 使用方式都是类似的。

1.1 执行命令行方式打包

pyinstaller  -w --add-data=Images:Images --add-data=engine_data:engine_data  chess_validate_main.py

输出如下:

$ pyinstaller  -w --add-data=Images:Images --add-data=engine_data:engine_data  chess_validate_main.py
506 INFO: PyInstaller: 6.6.0, contrib hooks: 2024.6
506 INFO: Python: 3.10.11
543 INFO: Platform: Windows-10-10.0.19045-SP0
545 INFO: wrote D:\python_project_2\chess_validate_tool\chess_validate_main.spec
548 INFO: Extending PYTHONPATH with paths
['D:\\python_project_2\\chess_validate_tool']
1017 INFO: Appending 'datas' from .spec
1019 INFO: checking Analysis
1019 INFO: Building Analysis because Analysis-00.toc is non existent
1019 INFO: Running Analysis Analysis-00.toc


.....


8741 INFO: checking COLLECT
8741 INFO: Building COLLECT because COLLECT-00.toc is non existent
8742 INFO: Building COLLECT COLLECT-00.toc
8977 INFO: Building COLLECT COLLECT-00.toc completed successfully.

这样dist 目录下会出现 如下的文件
在这里插入图片描述

1.2

执行完pyinstaller 命令后, 可以看到在当前目录下有一个 spec文件, 内容如下:

# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['chess_validate_main.py'],
    pathex=[],
    binaries=[],
    datas=[('Images', 'Images'), ('engine_data', 'engine_data')],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    [],
    exclude_binaries=True,
    name='chess_validate_main',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)
coll = COLLECT(
    exe,
    a.binaries,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='chess_validate_main',
)

这个就是我们打包的一个配置文件, 如果需求可以直接修改所需配置, 然后执行:

pyinstaller xx.spec

当然这个文件可以提前用单独的命令来生成:

 pyi-makespec.exe   chess_validate_main.py

1.3 问题

由于我的程序在运行过程中, 引用了第三方的一个 exe文件, 在打包完成后测试的过程中发现程序运行异常,不是我期望的运行表现,原因为: 上述打包过程禁用了console, 然而程序在打开第三方exe的时候没有禁用console, 导致了冲突, 修改源码在打开第三方程序的时候直接禁用console. 再重新打包, 运行正常。

2 cx_Freeze

直接安装 cx_freeze

 pip install cx-freeze 

安装成功后, 先看看需要哪些参数:

$ cxfreeze -h
usage: cxfreeze [--script NAME] [--init-script NAME] [--base NAME] [--target-name NAME] [--icon NAME] [--manifest NAME] [--uac-admin] [--uac-uiaccess] [--shortcut-name NAME] [--shortcut-dir DIR]
                [--copyright COPYRIGHT] [--trademarks TRADEMARKS] [--version]
                [COMMAND]

Freeze a Python script and all of its referenced modules to a base executable which can then be distributed without requiring a Python installation.

positional arguments:
  COMMAND               build, build_exe or supported bdist commands (and to be backwards compatible, can replace --script option)

options:
  --script NAME         the name of the file containing the script which is to be frozen
  --init-script NAME    script which will be executed upon startup; if the name of the file is not an absolute file name, the subdirectory initscripts (rooted in the directory in which the cx_Freeze        
                        package is found) will be searched for a file matching the name
  --base NAME, --base-name NAME
                        the name of the base executable; the pre-defined values are: "console" (default), "gui" and "service"; a user-defined base is accepted if it is given with an absolute path name      
  --target-name NAME    the name of the target executable; the default value is the name of the script; it is recommended NOT to use an extension (automatically added on Windows); target-name with version  
                        is supported; if specified a path, raise an error
  --icon NAME           name of icon which should be included in the executable itself on Windows or placed in the target directory for other platforms; it is recommended NOT to use an extension
                        (automatically added ".ico" on Windows, ".icns" on macOS and ".png" or ".svg" on Linux and others)
  --manifest NAME       name of manifest which should be included in the executable itself (Windows only)
  --uac-admin           creates a manifest for an application that will request elevation (Windows only)
  --uac-uiaccess        changes the application manifest to bypass user interface control (Windows only)
  --shortcut-name NAME  the name to give a shortcut for the executable when included in an MSI package (Windows only)
  --shortcut-dir DIR    the directory in which to place the shortcut when being installed by an MSI package; see the MSI Shortcut table documentation for more information on what values can be placed here  
                        (Windows only)
  --copyright COPYRIGHT
                        the copyright value to include in the version resource associated with executable (Windows only)
  --trademarks TRADEMARKS
                        the trademarks value to include in the version resource associated with the executable (Windows only)
  --version             show program's version number and exit

Note:
    * Windows only options are ignored by other OS and when used by Python app from Microsoft Store.

Additional help:
    cxfreeze build_exe --help

Linux and similar OS:
    cxfreeze bdist_appimage --help
    cxfreeze bdist_deb --help
    cxfreeze bdist_rpm --help
macOS:
    cxfreeze bdist_dmg --help
    cxfreeze bdist_mac --help
Windows:
    cxfreeze bdist_msi --help

为了快速验证, 直接执行下面的命令

cxfreeze --base-name=gui  --script chess_validate_main.py

运行结束后, 可以看到在build 目录有我需要的exe.
在这里插入图片描述
但是没有程序运行需要的资源文件, 需要手动copy Images 和 engine_data 到 exe所在的目录。

测试, 一下, 完美运行,由于在pyinstaller执行过的例子后实验, 相关坑已经踩过, 本次没有遇到任何问题。
附上运行截图
在这里插入图片描述

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值