小王平常的工作是做数据处理的,手中自然握有大量的数据,在日常工作中经常需要根据业务的需求提取相应的数据,有些需求是固定的,写好脚本之后只要定期提取数据就行了。
但是,像我这么懒的人,这种工作怎么可能自己做呢,于是就冒出一个想法,做一个带 GUI 界面的数据提取程序,想要数据的时候让业务自己点点点就行了,解放自己的双手那才是程序员的本职工作!
搜索了一下,如果用 Python 语言开发 跨平台 的图形界面的程序,主要有 3 种选择:
1、Tkinter 基于 Tk 的 Python 库,这是 Python 官方采用的标准库,优点是作为 Python 标准库、稳定、发布程序较小,缺点是控件相对较少。
2、wxPython 基于 wxWidgets 的 Python 库,优点是控件比较丰富,缺点是稳定性相对差点、文档少、用户少。
3、PySide2、PyQt5 基于 Qt 的 Python 库,优点是控件比较丰富、跨平台体验好、文档完善、用户多。 缺点是 库比较大,发布出来的程序比较大。
简单看了一下这几个方案,代码写起来都比较复杂,而且美观度较差,有没有快速又美观的方法呢?
其实我们可以直接将 Web 应用包装成一个可执行程序,拷贝到机器上就能运行,而且类似的框架很多,比如 Nodejs 中的 Electron,Python 中的 Pywebview。
只要将原来的 Web 程序包装一下就好了,那么说干就干!
Web 程序是用 Flask 开发的,所以需要安装 Python 的 Pywebview 作为打包工具。
pip install pywebview
小试牛刀:
import webview
window = webview.create_window('Hello!', 'http://http://www.justdopython.com')
webview.start()
就能看到如下的效果:
神奇吧!
Pywebview 支持三种模式,简单模式,服务器模式 和 线程模式。
对于现在的需求,我们选择服务器模式,即包装本地的一个 Web 应用。
服务器模式会为我们提供一个 HTTP Server,只要把 Web 应用部署上去就好了。
因为无非展示实际项目的代码,这里写一个简单的 Flask 应用:
创建一个 app.py 文件:
from flask import Flask, render_template, jsonify, request
app = Flask(__name__) ## 创建一个应用
@app.route('/')
def index(): ## 定义根目录处理器
return render_template('index.html')
@app.route('/detail')
def detail():
return render_template('detail.html')
if __name__ == '__main__':
app.run() ## 启动服务
这个应用很简单,只有两个页面,分别通过 / 和 /detail 来访问。
如果运行这段代码,就会启动一个 Flask 应用,通过 http://120.0.0.1:5000 来访问。
如何套在 Pywebview 中呢?
很简单:
import webview
from app import app
if __name__ == '__main__':
window = webview.create_window('Pywebview', app, height=600, width=1000)
webview.start()
这里的关键是,将 Flask 应用作为 url 参数,Webview 发现传入的参数是 flask 应用,就会启动服务模式。
运行程序后,可以看到和在浏览器中的效果一样的:
现在就可以将这个项目打包成 exe 了。
首先需要安装 pyinstaller
pip install pyinstaller
然后进入程序目录执行:
pyinstaller -F -w main.py
很快在程序目录下,就会生成一个 dist 文件夹,其中就会有个 main.exe 可执行文件,这就是打包好的结果。
双击运行,可以看到效果……
等等,好像并不是想象中的那样!
这是怎么回事呢?
根据提示来看,是因为找不到页面的模板文件。
我们在前面创建 Flask app 时,使用的是默认的模板路径,即 app.py 文件所在目录的 templates 目录,为啥打包之后就找不见了呢?
这是因为在 windows 中,可执行文件的运行时,会被解压到一个特定的目录下,而我们的模板文件并没有被打包进入 exe 文件中,所以导致运行时找不见模板文件。
如何解决这个问题呢?
作为不使用外部数据或文件的程序,只需要将程序本身打包就可以了,但大部分程序都需要外部数据,比如我们的 Flask 应用,就需要用到静态文件等。
那么如何将它们打包进可执行文件呢?
只需要在打包时多加一个参数就可以了:
pyinstaller main.py -F -w --add-data "./templates/*;templates"
– add-data 参数表示添加额外的数据 ./templates/* 表示需要添加当前目录的 templates 目录中的所有文件 ;为分隔符,其后的 templates 表示解压是这些数据所在的目录,这个目录名必须和 创建 app 时 >template_folder 参数一致 如果需要用到静态文件,需要额外添加,比如 –add-data “./static/*;static”
这样就能将外部数据一起打包进来了。
打包好后,双击执行,就会发现网页得以完美呈现了。
注意:
如果使用了虚拟环境,必须在虚拟环境中单独安装 pyinstaller,而不能用其他环境中已经安装好的,这是为了包装打包是可以链接所以程序引用的模块
因为 pyinstaller 打包时,找不到被引用的模块时并不报错,而打包好的程序可能会无法执行。
Python小技之不用 GUI,照样实现图形界面 https://mp.weixin.qq.com/s/o5aBMu23_SSzpvsZ3tnObQ