V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
ignor
V2EX  ›  Python

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

  •  
  •   ignor · 179 天前 · 1940 次点击
    这是一个创建于 179 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    第 1 条附言  ·  179 天前
    想通了,哪怕只有一个交互式弹框,程序的性质就变成 GUI 程序了。考虑到将来对话框可能变复杂,将 GUI 线程提到主线程,业务跑在新线程,应该是最简单有效的做法,也便于后面进一步分离 GUI 和业务
    21 条回复    2023-10-28 22:42:26 +08:00
    luckyrayyy
        1
    luckyrayyy  
       179 天前
    进程间通信有啥小题大做的
    geelaw
        2
    geelaw  
       179 天前 via iPhone
    最简单的方法是在最开始开一个新的线程运行原来主线程的代码。

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

    所有的 UI 框架(安卓,ios ,win32 ,swing ,qt ,Web ,js ,UE UNITY 等若干)都不支持子线程更新 UI 或者说是做不到 UI 更新线程安全,所有 UI 框架都采用 eventloop 的方式,无数人在这个地方踩过无数坑了。
    Sun 的副总裁曾经有个博客讲过这个事: https://zhuanlan.zhihu.com/p/44639688
    ignor
        19
    ignor  
    OP
       179 天前 via iPhone
    @4kingRAS js 写了也有上万行了吧,从没想过……但可能正是因为 js 用的事件驱动,所以遇不到这样的问题
    koast
        20
    koast  
       178 天前
    这需求多少看起来感觉有点别扭,C#里解决这个事情的方法倒是有点特别,用委托,给委托注册上处理函数,然后就可以在子线程里以主线程的身份进行函数调用了。python 里的话,感觉还是#4 的方法最简单。
    ysc3839
        21
    ysc3839  
       177 天前 via Android
    Windows 的话直接开多个线程显示即可,Linux 我不清楚,macOS 是限制只能在主线程使用 UI 相关 API 的。
    因此如果只是为了显示个通知啥的,跨平台的方案是直接用一个独立的进程。
    另外 macOS 还有个限制,就是 fork 后如果没有 exec ,那包括 UI 在内的很多系统 API 都不可使用。
    @4kingRAS Win32 控件是允许不同线程进行更新的,因为控制都是通过窗口消息进行的,而窗口消息处理函数本身会保证只会在窗口所在线程执行。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3362 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:11 · PVG 20:11 · LAX 05:11 · JFK 08:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.