Python 如何在非主线程里实现一个弹窗式对话框?

2023-10-26 21:18:15 +08:00
 ignor

现在有一个 python 程序,主线程在跑 flask ,同时运行了若干个子线程,这些子线程中如果有异常,需要做个弹框提示,点击 OK 或 Cancel 决定是否发送错误报告。

本想着直接拿 tkinter 简单弄一下就完事,但这些 GUI 框架似乎都只能在主线程里面跑 mainloop…… 如果另起一个进程来运行对话框,又涉及进程间通信,是不是有点小题大做了?想知道有没有简单点的办法呢?

2225 次点击
所在节点    Python
21 条回复
luckyrayyy
2023-10-26 21:24:54 +08:00
进程间通信有啥小题大做的
geelaw
2023-10-26 21:26:21 +08:00
最简单的方法是在最开始开一个新的线程运行原来主线程的代码。

我不了解 tkinter 和 flask ,如果你告诉我两个都需要在主线程运行,那就必须重新编程。(但我不能理解为什么一个库要令主线程是特殊的。)
yolee599
2023-10-26 21:27:19 +08:00
正规做法就是用进程间通讯做的啊,mainloop 只跑 gui
ding2dong
2023-10-26 21:34:28 +08:00
新增一个弹窗脚本,用 subprocess.run()调用该脚本,根据返回值判断是否需要发送错误报告。不知这样可否?
darcyC
2023-10-26 22:23:10 +08:00
用 4 楼说的方法 或者就是你说的 进程间通讯,tkinter 只能运行在主线程 同时 flask 的部分功能也只能运行在主线程(见 https://stackoverflow.com/questions/31264826/start-a-flask-application-in-separate-thread )我个人推荐你用 4 楼的方法吧
hefish
2023-10-26 22:36:54 +08:00
楼上的列位大佬,OP 的意思就是不用进程间通信,但还是得把进程间通信的事儿给办了。 大家按照这个思路来。。。
qbqbqbqb
2023-10-26 23:11:10 +08:00
tkinter 可以在子线程里用 event_generate 产生一个事件,然后主线程挂一个 handler 来处理
ignor
2023-10-26 23:13:54 +08:00
好吧,之前没做过 GUI ,原来弹个框是这么麻烦的事……
想了一下,这个通信过程有点不知道该怎么处理合适?我希望能封装成一个通用的方法,每次需要弹框就调用一下,大佬们有没有好的实践思路?
coolair
2023-10-26 23:27:35 +08:00
用 pyqt 啊,跟前端一样 emit 啊,gui 主线程就能接收到其他线程 emit 来的数据,然后弹窗就可以了啊。
ignor
2023-10-26 23:37:17 +08:00
@coolair pyqt 的 gui 主线程也是 python 的主线程吧?这里的问题是主线程已经被 flask 占用了
neoblackcap
2023-10-26 23:48:14 +08:00
@ignor 所有的带 GUI 的程序,主线程都是指 gui mainloop 所在的线程。因为只有它才能绘制图像不出错。
事实上你应该先启动 GUI 主线程,然后再通过 worker 线程来跑 flask 。然后所有跟 GUI 相关的问题都可以归纳回如何跟主线程通信了。
fgwmlhdkkkw
2023-10-26 23:54:17 +08:00
有错误存到数据库,然后做 api ,调用浏览器打开。
这页面里使用 websocket 连接,这个服务器可以判断有没有正在浏览的页面。
duke807
2023-10-27 00:04:45 +08:00
非主线程里实现一个弹窗式对话框,或者显示单独的窗口,都是很轻松的啊,linux 、windows 都没问题,macos 除外
ksc010
2023-10-27 00:22:05 +08:00
有个疑问,子进程遇到异常后,还继续执行吗?
NoOneNoBody
2023-10-27 01:52:39 +08:00
import easygui
...
nuk
2023-10-27 02:57:26 +08:00
简单点就直接 messagebox ,同步调用用不着 mainloop
vialon17
2023-10-27 08:41:47 +08:00
我最近倒是做了一个主 qt+flask 的应用,直接开 qthread 包裹一下 flask 就可以了。
弹窗直接用 qt 模板就行。
4kingRAS
2023-10-27 10:44:57 +08:00
程序写少了,稍微接触过 JS 就可以很轻松理解这个问题。

所有的 UI 框架(安卓,ios ,win32 ,swing ,qt ,Web ,js ,UE UNITY 等若干)都不支持子线程更新 UI 或者说是做不到 UI 更新线程安全,所有 UI 框架都采用 eventloop 的方式,无数人在这个地方踩过无数坑了。
Sun 的副总裁曾经有个博客讲过这个事: https://zhuanlan.zhihu.com/p/44639688
ignor
2023-10-27 11:44:44 +08:00
@4kingRAS js 写了也有上万行了吧,从没想过……但可能正是因为 js 用的事件驱动,所以遇不到这样的问题
koast
2023-10-27 21:03:17 +08:00
这需求多少看起来感觉有点别扭,C#里解决这个事情的方法倒是有点特别,用委托,给委托注册上处理函数,然后就可以在子线程里以主线程的身份进行函数调用了。python 里的话,感觉还是#4 的方法最简单。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/985783

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX