Automate packaging NiceGUI apps with PyInstaller and releasing them with Github Actions

这是我之前在个人网站上发布的一篇旧博客文章。我正在将所有内容转移到CSDN。感谢阅读!


Having learned the practice of CI/CD, I decided to apply this technique to continuously deliver some of my projects starting with a recent NiceGUI app – File Copier.

在这里插入图片描述
如果您在PC上的微信文件夹中有需要的文件,并且不想打开每个子文件夹来搜索这些文件,您可以使用File Copier。只需将其指向微信文件夹位置,指定文件类型名,它就会将所有内容复制到一个目标文件夹中。在一个文件夹而不是数百个文件夹中很容易找到重要文件。我没有找到任何这样的应用,所以我自己做了一个。

该应用程序未经测试,因此仅用于学习目的

Initially, I went to Github Marketplace and searched for pre-build PyInstaller actions. Because I’m packaging for the Windows platform I ended up selecting PyInstaller Windows which is the most popular action in the category at the time of writing.

- name: PyInstaller Windows
  uses: JackMcKew/pyinstaller-action-windows@main
  with:
    path: src

The above code snippet shows how easy it is to integrate this action into the workflow. However, I encountered three problems with this approach:

  • the first one is architectural – despite being Windows-oriented, this action runs inside a Linux (Ubuntu) container and uses Wine for cross-compilation. The reason for this is that PyInstaller currently does not cross-compile executables meaning that it cannot produce .exe files on Linux, therefore there is the need for a translation layer – Wine. Since 2021, Github gives you the ability to run workflows inside a Windows container which reduces the complexity and basically makes the aforementioned action obsolete.
  • the second problem is related to NiceGUI and the way it needs to be discovered by PyInstaller. It requires the use of an intermediary step – running a build.py file by the Python interpreter. Since PyInstaller Windows abstracts away the run steps, there is no way to properly configure NiceGUI for PyInstaller.
  • the third one is also architectural and requires generating a .spec file on a local machine before committing it into a remote repository for later use in an actual workflow, which in my opinion, defeats the purpose of CI/CD.

With that said, there was the need for an alternative approach. Below is what I was able to come up with.

name: Python application

on:
  push:
    tags:
      - v*

permissions:
  contents: write

jobs:
  build:
    runs-on: windows-2019

    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v3
        with:
          # python-version: "3.8"
          # python-version: "3.9"
          python-version: "3.10"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          python -m pip install -r requirements.txt
      - name: PyInstaller
        run: |
          python build.py

      - name: Release
        uses: technote-space/action-gh-release@v2
        if: startsWith(github.ref, 'refs/tags/')
        with:
          files: ./dist/file-copier.exe
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

First, we set up the trigger – a push event on the tags which help us mark a commit for release. We can add tags with the folloing command: git tag -a v1.0 -m "Release version 1.0". Later when we push changes to the main branch we also push them on the tag: git push origin main v1.0 which activates the release action.

Second, we set up write access to the repository for uploading a compiled executable to releases. Then, we specify the container for the jobs to run inside of – in this case windows-2019. Now onto the actual workflow:

  • we set up Python 3.10 environment and install our project requirements
  • we run the build.py file as documented here but with minor modifications. First is the “–name” that specifies the filename of our future executable – in my case file-copier.exe. Second is the --onefile flag. Currently, it is not possible to correctly package pywebview with PyInstaller (which is what nicegui internally depends on) on Github Actions with the --onedir flag due to a regression in another package – pythonnet. One comment proposed to downgrade pythonnet from version 3 to version 2.5.2, however because there is no binary wheel available for version 2.5.2 for Python 3.10, building it from source inside Github Actions results in an error due to a missing compiler. One possible way to resolve this error is to try older versions of Python – 3.9 or 3.8. Another problem I faced is that executables built with the --onefile flag may false-trigger an antivirus on the end-user machine, as --onefile executables unpack themselves on each run which is similar to how many malicious programs behave. In this case, the antivirus can delete the executable. One can instruct the user to restore the file from quarantine and assure him or her of its safety. As I said, one can try different Python versions to try and downgrade the pythonnet package and test the result.

Update: While it is possible to downgrade and build the pythonnet package with Python 3.8 and 3.9 in a Windows container on Github Actions, running the final executable still results in an exception.

import os
import subprocess
from pathlib import Path

import nicegui

cmd = [
    "python",
    "-m",
    "PyInstaller",
    "--noconfirm",
    "main.py",  # your main file with ui.run()
    #
    "--name",
    "file-copier",  # name of your app
    #
    # "--onedir",
    "--onefile",
    #
    "--windowed",  # prevent console appearing, only use with ui.run(native=True, ...)
    #
    "--add-data",
    f"{Path(nicegui.__file__).parent}{os.pathsep}nicegui",
]
subprocess.call(cmd)
  • finally, we set up the release action technote-space/action-gh-release@v2 and point it to the newly built executable ./dist/file-copier.exe

After all these steps are done with, we can see the v1.0 release on the repository page.

《用Python自动化无聊的事情》是一本由Al Sweigart所著的非常受欢迎的技术书籍。该书侧重于利用Python编写脚本来自动执行一些无聊的、重复性的任务。 在如今数字化时代,我们面临着许多重复性的任务,这些任务可能会浪费我们的时间和精力,例如处理大量的电子表格、文本文件和网页数据。而《用Python自动化无聊的事情》教会了我们如何使用Python编程语言来解决这些问题。 首先,该书介绍了Python编程语言的基础知识,包括变量、数据类型、循环、条件语句等等。然后,它深入讲解了Python的各种库和模块,如openpyxl、PyPDF2、selenium等,这些功能强大的库使我们能够处理各种不同类型的数据,并将其自动化。 《用Python自动化无聊的事情》还教会了我们如何使用正则表达式进行模式匹配,如何利用Python处理电子邮件、自动化生成文档和报告,以及如何自动化网页浏览。 正如书名所说,Python是一种强大的脚本语言,可以帮助我们摆脱那些枯燥乏味的任务,并节约大量的时间和精力。通过使用Python编写脚本,我们可以轻松地处理和分析大量的数据,自动执行各种任务。 总而言之,通过阅读《用Python自动化无聊的事情》,我们可以学习如何使用Python编写脚本来自动化各种任务,节约时间,并提高工作效率。无论是日常生活中的任务,还是在工作中遇到的问题,利用Python来自动化处理都是一个非常有用的技能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值