如何部署pyside2应用程序? -Qt方式

时间:2019-04-06 01:01:19

标签: python qt qt5 pyside2

我需要为所有主要的3种操作系统(Windows,Linux和MacOS)部署基于 Qt 5.12.1 pyside2 应用。

我已经检查了How to make a Python script standalone executable to run without ANY dependency?,但这不是我想要的,因为我需要与Qt相关的方法,例如windeployqtmacdeployqtlinuxdeployqt(独立项目)。

如eyllanesc所指出:“ python是一种不会生成二进制文件的脚本语言” 。但是,Qt公司也应该考虑到这一点,并使我们更容易部署 pyside2 应用程序。至少与部署C ++ / QML应用程序一样容易。

所以我想要一个像 windowsdeployqt macdeployqt linuxdeployqt 这样的工具,它可以与 pyside2 应用程序一起使用

[UPDATE] eyllanesc建议以fbs (fman build system)作为起点,因为尚无用于部署 pyside2 应用程序的官方工具。这应该作为一种解决方法。也欢迎新的答案。
The Qt Company发布正式工具后,请尽快回答。

[注意]::我正在使用基于 Qt 5.12.1

Qt Creator 4.8.1

2 个答案:

答案 0 :(得分:2)

当前没有Qt方式来部署PySide2应用程序(而且我认为至少在不久的将来不会有这种方式)

关于此主题,有以下报告:PYSIDE-901PYSIDE-913,其中指出可能是针对Qt for Python 5.13的文档将更新,并且会有一部分用于部署。您可以看到进度here

其中3个选项可以进行部署:

  

项目的选项是:
  1.发送带有应用程序内容的普通zip文件。
  2.构建适当的Python程序包(轮子):https://packaging.python.org
  3.将应用程序冻结在单个二进制文件或目录中。

在第三种方法中,他们对PyInstallercx_Freezepy2exepy2app之类的工具的优缺点进行了评论,最终表明最佳选择对于他们来说是cx_Freeze或Pyinstaller。还有一个有趣的工具是fbs项目(基于Pyinstaller)。

我个人认为fbs是因为它提供了一种基于PyQt5或PySide2打包项目的简单方法

答案 1 :(得分:1)

将所有必需的依赖项打包在一个文件夹中,然后分发。

简单的想法,但问题在于找到最小的集合。在qt网站上提出的打包程序会创建复杂的文件结构和它们自己的EXE,对于小脚本案例(IMHO)而言,这太多了。 幸运的是,有一些方法可以记录依赖项:在Windows上为Process Monitor,在Linux上为strace。它们列出了受监视程序的所有系统调用。我写了一个小python脚本来从此类日志中选择依赖项。

在如下所示的虚拟环境中执行此操作很方便,或者在预安装了基本模块的python嵌入式发行版中进行此操作:

    > python -m venv ./MyVEnv
    > cd ./MyVEnv
    > ./.../python -m pip install pyside2
  1. 启动syscall监视器(即使10秒日志也是如此,所以不要长时间运行)并启动使用Qt加载所有依赖项的脚本(使其执行所有可能的操作以打开所有必要的依赖项)和关闭(以解锁锁定的对象);使用cpython的-B标志可能会很有用,以避免在最终文件包中缓存文件;您也可以在监控程序中手动过滤掉不必要的系统调用以减少日志

在Windows上:

    > Procmon /AcceptEula /NoFilter /BackingFile log1
    > .\MyVEnv\...\python -B yourScript.py
    > Procmon.exe /OpenLog log1.PML /SaveAs logFile.csv

在Linux上:

    > 2>logFile strace ./bin/python3 -B yourScript.py
  1. 在启动我的脚本之后,将所有记录的依赖项复制到一个文件夹中,并保留原始文件结构:

    > python .\depspicker.py
    

这是:

    #depspicker.py
    #changes from Windows to Linux version commented

    logF = r".\logFile.CSV" #Linux: ./logFile
    basePath = r".\...\site-packages" #base of the file-tree to be copied (where the needed dependencies originally reside)
    destPath = r".\site-packages" #destination of copy


    import csv, shutil
    from pathlib import Path

    logF = Path(logFile)
    basePath = Path(basePath).resolve()
    destPath = Path(destPath).resolve()

    with open(logF, newline='', encoding="utf-8") as log:
        checked = set()
        reader = csv.DictReader(log) # Linux: -
         for row in reader: #Linux: for row in log:
            try:
                src = Path(row["Path"]) # Linux: src = Path(row.split('"')[1])
                src = src.resolve()
                if src in checked or not (src.is_file() and\
                    basePath.parts == src.parts[:len(basePath.parts)]):
                    continue
            except (OSError, IndexError): #not a file
                continue
            finally:
                checked.add(src)
            dst = destPath / src.relative_to(basePath)
            dst.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy2(src, dst.parent)
  1. 现在您可以用复制的文件树从“ destPath”到可用空间替换“ basePath”中的所有内容;要分发您的程序,您可以将python嵌入,将新的依赖项放到那里,并以类似的方式进一步删除所有不必要的文件-或从一开始就使用嵌入式而不是venv