我是靠谱客的博主 温柔小兔子,最近开发中收集的这篇文章主要介绍使用Python+Flask开发桌面应用的新选择-flaskwebgui前言官网效果演示项目文件结构main.py代码index.html代码打包成EXE结束语BUG处理更新: 使用pyinstaller打包为单个EXE文件需要注意的问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

之前分别用过了eel, pywebview进行桌面应用开发, 但是都有不太理想的地方, eel没有对flask的原生支持, 而pywebview虽然可以直接将flask的实例对象进行传递, 用起来也挺方便, 不过在调用浏览器引擎方面有点难受, 要么用cef, 就得带进去一大堆依赖, 如果用pyinstaller打包后还会出现各种跑不起来的坑, 要么就是用IE内核, 那简直要了亲命的, 还不能指定调用外部的Chrome浏览器进行渲染, 很是尴尬…要是能有一个轮子结合eelpywebview的优点, 可以直接用flask+Chrome跑的话那就完美了, 嘿嘿~还真让我给翻出来了: flaskwebgui, 下面开始实例记录一个小demo

官网

https://github.com/ClimenteA/flaskwebgui

是个19年开始做的项目, 更新还是蛮频繁的, 感谢作者ClimenteA

pip直接安装就行

pip install flaskwebgui

效果演示

auto-py-to-exe打包后扔到纯净的Win7虚拟机中进行测试, 除了需要单独安装一下Chrome以外, 不需要任何运行环境即可直接跑起来.
在这里插入图片描述

项目文件结构

就是正常的一个flask应用的结构, 这里我用了CDN, 没有加static文件夹

.
├── main.py				# 入口程序
└── templates
    └── index.html		# 页面模板

main.py代码

from flask import Flask, render_template
from flaskwebgui import FlaskUI

# 正常实例化flask对象
app = Flask(__name__)
# 将app对象传入FlaskUI的构造函数中, 并设置要打开的窗口尺寸
ui = FlaskUI(app, width=800, height=600)


@app.route('/')
def index():
    return render_template('index.html')


if __name__ == '__main__':
	# 注意这里调用的是ui的run
    ui.run()

index.html代码

纯前端的代码, 其实没啥好贴的了, 从layui文档里面抄了一段后台模板测试下. 主要就是一个需要注意的地方, 记得设置页面的语言<html lang="zh">, 否则调用Chrome的时候会提示是否需要进行翻译, 比较讨厌.

<!DOCTYPE html>
<html lang="zh">    <!--注意设置语言, 否则调用Chrome打开会出现是否翻译的提示-->
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flaskwebgui演示程序</title>    <!--这里将会是打开的Chrome标题-->
</head>

<body>
    <div class="layui-layout layui-layout-admin">
    中间省略了, 没啥参考价值
    </div>
</body>
</html>

打包成EXE

这里还是用auto-py-to-exe, 比手工配置pyinstaller更方便, ps: 这货是eel写的

pip install auto-py-to-exe
auto-py-to-exe

注意把templates文件夹添加到打包的选项里就行
在这里插入图片描述
默认参数打包后的文件夹大小22MB多点
在这里插入图片描述
开UPX压缩试试:
在这里插入图片描述
直接干掉一半大小, 变成10MB了, 哇哈哈哈哈
在这里插入图片描述
然而…启动upx压缩后的程序报错:
在这里插入图片描述
在这里插入图片描述
本着这种问题我肯定不会是第一个发现的原则, 果然在stackoverflow上找到了病友:
https://stackoverflow.com/questions/38811966/error-when-creating-executable-file-with-pyinstaller

upx压缩的时候把VCRUNTIME140.dll给干残了, 单独设置一下不压缩这个文件, 注意上面设置的--upx-dir参数不变, 额外添加手动参数: --upx-exclude=vcruntime140.dll, 这样完整的命令:

pyinstaller --noconfirm --onedir --windowed --upx-dir "D:/tools/upx-3.96-win64" --add-data "C:/Users/Lian/Desktop/flaskgui/templates;templates/" --upx-exclude=vcruntime140.dll "C:/Users/Lian/Desktop/flaskgui/main.py"

再打包, 文件夹就大了0.1MB而已, 这次运行正常! 整个文件夹再打个zip, 只有9MB了, 好吧, 承认是我强迫症犯了…
在这里插入图片描述
进行应用分发的时候可以直接把这个压缩包+Chrome的standalone安装包扔给用户, 先装Chrome, 然后再解压执行main.exe就可以了.

结束语

这么一来的话, Chrome居然变成了运行环境RUMTIME, 不过相对于之前用.Net Framework做Winform类的桌面应用而言, 这种方式算是完美结合了WEB技术出炫酷的UI界面+Python各种轮子快速实现业务逻辑的优势, 当然缺点嘛, 可能就是第一次启动程序调用Chrome的时候会有点略慢, 不过关掉后再启动就挺快了.

BUG处理

这貌似是当前版本存在的bug, 就是在关闭浏览器之后, 后台的flask进程并没有自动退出, 看了下GitHub上的issue, 果然我又不是第一个哈哈哈哈:

https://github.com/ClimenteA/flaskwebgui/issues/58

根据热心网友提出的方案, 改一下flaskwebgui.py源代码313行的while True:开始的内容, 加一层try except来捕获异常强制退出flask就行了, 修改后的这部分代码:


        while True:
            try:	# 增加的内容
                gui_running = psutil.Process(
                    self.BROWSER_PROCESS.pid).is_running()
                gui_memory_usage = psutil.Process(
                    self.BROWSER_PROCESS.pid).memory_percent()

                if (
                    gui_running == False
                    or
                    gui_memory_usage == 0
                ):
                    break

                time.sleep(5)
            except Exception as e:	# 增加的内容
                logging.info('Forced Shutdown Browser Closed')
                break

        if isfunction(self.on_exit):
            logging.info(f"Executing {self.on_exit.__name__} function...")
            self.on_exit()
        else:
            logging.info("No 'on_exit' function provided.")

        logging.info("Closing connections...")
        FlaskUI.kill_pids_by_ports(self.port)

估计后续的更新可能会修复这个bug吧, 可以跟进一下这个项目了, 真的很不错!

更新: 使用pyinstaller打包为单个EXE文件需要注意的问题

又尝试了一下在auto-py-to-exe中打包成单个可执行文件, 对于额外引入的templates文件夹, 需要在主程序中修改一下访问路径的逻辑, 不能直接用默认的, 看代码吧:

import os
import sys
from flask import Flask, render_template
from flaskwebgui import FlaskUI

# 使用pyinstaller打包成单文件需要处理路径问题
app_path = ''
if hasattr(sys, '_MEIPASS'):	# 如果是单个EXE文件执行的时候sys中会存在这个_MEIPASS变量作为当前的工作根路径
    app_path = os.path.join(sys._MEIPASS)

# 拼接一下获得模板文件夹所在的绝对路径, 这样写不会影响打包前对源代码的调试
template_folder = os.path.join(app_path, 'templates')

# 实例化Flask对象的时候就得指定一下template_folder的位置了, static文件夹同理.
app = Flask(__name__, template_folder=template_folder)

附上打包成单个EXE文件后的运行效果, 只有9MB哦! 估计是用CDN的原因, 启动的前两秒空白等待了一会儿, 还是把静态资源打包到程序里面比较好.
在这里插入图片描述

最后

以上就是温柔小兔子为你收集整理的使用Python+Flask开发桌面应用的新选择-flaskwebgui前言官网效果演示项目文件结构main.py代码index.html代码打包成EXE结束语BUG处理更新: 使用pyinstaller打包为单个EXE文件需要注意的问题的全部内容,希望文章能够帮你解决使用Python+Flask开发桌面应用的新选择-flaskwebgui前言官网效果演示项目文件结构main.py代码index.html代码打包成EXE结束语BUG处理更新: 使用pyinstaller打包为单个EXE文件需要注意的问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部