最近一段时间闲来无事,简单研究了一下pyside6,也就是PyQt5的升级版。做这个的目的,也是回顾下桌面开发的基础,兴许未来可能用得上。虽然在日常工作中,可能用到桌面开发的场景比较少,桌面工具的成果也比较难包装,但有一个这样的工具,确实可以解决许多工作效率方面的问题。
在之前笔者也写过几篇pyside6文章,但不是特别系统,比如说:
- pyside6安装
- pyside6绘制时钟
因此,今天这篇文章就系统分享一下,怎么样用pyside6写一个postman接口调用的小功能,开发并部署出来。作为一个自己写的教学文章,这篇文章会重点提一些自己觉得实操过程中的要点,少一些ChatGPT就能回答的东西。有了这些基础之后,做其他的工具需求,也会变得更加简单一点。
项目初始化
安装方面不再赘述,详情可以看官网的Getting Started以及Tools的部分,然后先前的文章也基本上把目录组织和最小demo给讲清楚了。
核心要解决的问题就是通过目录组织,把工作流的每一个模块给拆出来,互不影响。比如这样:
- pyside6-designer:.ui文件
- ui定义py文件
- 继承ui,具体view的py文件
- viewmodel层
- service、config之类,和界面无关的底层逻辑
- util工具类
界面设计
界面设计上,用一个TabWidget就可以简单做个门户入口,区分多个子功能的界面,每个子功能也可以单独在一个ui界面去设计。
每一个Widget里面需要定义组件的排版(layout),在designer里面,一般是Widget包含了一个组件才能够编辑layout。layout有很多种,垂直(vertical)的话类似于web前端里面一个个Row的排列,水平(horizontal)的话则类似于一个个Col的排列,栅格(Grid)布局的话每个组件的占用面积可能和旁边组件相关联,还有一种表单(Form)布局则专门用于填写表单配置类,是label+input的阻塞。
在layout限制下,每个组件可能占据一块区域,但组件自己也有一些填充策略。像PushButton,一般水平或垂直策略需要调整成fixed,保证不填充到整个区域,要按照自己本身的大小来填,而比如Spacer,需要做占位把组件分割成左右两块的,默认会设置成Expanding来占位。
layout的作用,比方说,做一个json格式转换工具,可以先用一个HorizontalLayout设置两行,第一行工具栏,第二行是TextEdit输入输出界面。工具栏设置成VerticalLayout,装几个Button外加Spacer填充空位,输入输出可以直接占第二行的左右两边,也是搞成VerticalLayout。右边的TextEdit弄成只读,左边的TextEdit用于输入yaml、json等字符串,这样再结合自己实现的model跟service逻辑,整个模块就差不多做起来了。
postman逻辑编写
工具逻辑方面,本文就给一个简单的postman工具实现,满足调http接口拿返回信息的一个需求。没有全部源码,没有一张图片,只说要点。
首先,界面设计方面,直接抄postman的一些基本元素就可以了,比如说:
- Request:Method、URL、SubmitButton、Headers、Body、Settings
- Response:Headers、Body、StatusCode、ElapsedTime
每个组件可能还有比较细微的需求,比如Headers可以做成QTableWidget的形式,支持增删改功能,用setRowCount、setItem、removeRow之类的接口就可以满足这些操作。Settings可以简单做成FormLayout,设置超时时间就可以。ElapsedTime则在ui设计上需要留空内容,请求的时候动态渲染当前请求消耗了多少秒钟。
ui设计差不多好了之后,我们需要写单独的一个http请求模块,让http请求的执行和审计可以独立出来运行。这是因为,桌面工具ui渲染是大头,不是说执行了一个http请求ui渲染就会阻塞,这样界面就会卡住了。怎么样不让界面卡住这是另一个话题,先解决http请求,让其可以单独执行。
我们可以基于requests库来实现http调用逻辑,需要单独把Request和Response类抽象出来。直接上代码:
1 | import requests |
有了这些代码之后,单个http请求就可以独立运行,并且请求、返回的数据上下文也可以单独审计。
接下来要解决的问题是,怎么把view逻辑和这个request串联起来。这里需要用到QThread加上signal的机制,通过一个RequestWorker串联,保证http请求干扰不到ui运转。
View层面,逻辑可以简写成这样:
1 | class ToolWidget(QWidget): |
而RequestWorker可以这样写:
1 | # 省略imports |
这样,通过在worker里把request放到ProcessPoolExecutor里另一个进程,实时监控执行,再结合signal机制防止view层阻塞,就可以把简单的http请求能力串联起来。至于想了解ProcessPoolExecutor怎么运作的,可以参考笔者以前写的这篇文章。
项目部署
部署方面可以参考官网Deployment文档,采用pyside6-deploy工具来做二进制的部署。部署本身可能需要安装其他的python库,比如Nuitka,这些在自己的python环境里准备就好。部署默认会生成pysidedeploy.spec文件,是部署的配置文件,如果有部署不成功的问题可以改配置文件解决,比如:
- project_dir:项目路径,相对于你运行部署的路径,填写一个点就行
- input_file:相对的入口文件路径,比如main.py
- exec_directory:相对的输出路径,比如output、build、dist之类,按自己情况来
- python_path:venv可以设置成绝对路径
- packages:可以指定某些库要安装,如果当前python版本没有对应库的话可以改版本号试试
- qml_files:相对的qml文件路径。没有qml的话,需要随便指定某个文件,不然会把整个项目include进去,venv开发的话过不了
设置好了跑通之后,预期就会在exec_directory生成二进制文件了。