如何从同一个Python程序运行Flask和QApplication

问题描述 投票:0回答:1

我正在尝试创建一个简单的休息端点,当点击时,它会更改程序本身安装的托盘图标的状态。

我相信我需要 Flask 和 QApplication 在不同的线程中运行,我尝试这样做。

但是我不熟悉Python,很可能我在下面做错了什么:

import sys
import asyncio
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (
    QSystemTrayIcon, 
    QApplication, 
    QWidget
    )
from flask import Flask 



async def gui():
    app = QApplication(sys.argv)
    w = QWidget()
    trayIcon = QSystemTrayIcon(QIcon("disconnected.png"), w)
    trayIcon.show()        
    print("running gui")
    return app.exec()


async def rest():
    app1 = Flask(__name__) 
    
    @app1.route("/connect") 
    def connect(): 
        return "I will signal gui to change icon to connected"
    @app1.route("/disconnect") 
    def disconnect(): 
        return "I will signal gui to change icon to disconnected"

    print("creating rest endpoint")
    return app1.run()  



async def main():
    return await asyncio.gather(gui(), rest() )

if __name__ == "__main__":
    asyncio.run(main())





当我运行上面的代码时,我只看到“正在运行 gui”,并且我可以看到托盘图标被安装到状态栏。我没有看到“创建休息端点”

如果我注释掉“return app.exec()”。我看到“正在创建休息端点”并且可以访问端点,但没有看到托盘图标。

我错过了什么?

额外信息:这是我的

Pipfile
(使用
pipenv

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
pyqt6 = "*"
flask = {extras = ["async"], version = "*"}

[dev-packages]

[requires]
python_version = "3.10"
python flask pyqt pyqt6
1个回答
0
投票
当程序在其代码内部使用

ayncio

 时,
await
很有用 - 在
app.run()
app.exec()
内部 - 但据我所知,
Qt
Flask
不这样做。 (但也许
Flask
有使用
asyncio
的版本)

您可能需要使用线程在单独的线程中运行程序(或者一个程序在单独的线程中运行,其他程序在当前线程中运行)。

版本 1:两个程序都在单独的线程中

def gui(): # without `async
    #...

def rest(): # without `async
    #...

if __name__ == "__main__":
    from threading import Thread
    
    t1 = Thread(target=gui)
    t2 = Thread(target=rest)
    
    t1.start()
    t2.start()
    
    # it blocks this function and wait for end of threads
    t1.join()
    t2.join()  

版本 2:一个程序在单独的线程中,另一个程序在当前线程中

def gui(): # without `async
    #...

def rest(): # without `async
    #...

if __name__ == "__main__":
    from threading import Thread
    
    t1 = Thread(target=gui)
    t1.start()

    rest() # it blocks this function

    # wait for end of thread
    t1.join()

完整的工作代码

import sys
import asyncio
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (
    QSystemTrayIcon, 
    QApplication, 
    QWidget
    )
from flask import Flask 


def gui():
    app = QApplication(sys.argv)
    
    w = QWidget()
    trayIcon = QSystemTrayIcon(QIcon("disconnected.png"), w)
    trayIcon.show()        
    
    print("running gui")
    
    app.exec()


def rest():
    app = Flask(__name__) 
    
    @app.route("/connect") 
    def connect(): 
        return "I will signal gui to change icon to connected"
        
    @app.route("/disconnect") 
    def disconnect(): 
        return "I will signal gui to change icon to disconnected"

    print("creating rest endpoint")
    
    app.run()  


def version_1():
    from threading import Thread
    
    t1 = Thread(target=gui)
    t2 = Thread(target=rest)
    
    t1.start()
    t2.start()
    
    # it blocks this function and wait for end of threads
    t1.join()
    t2.join()

def version_2()
    from threading import Thread
    
    t1 = Thread(target=gui)
    t1.start()

    rest() # it blocks this function

    # wait for end of thread
    t1.join()


if __name__ == "__main__":
    #version_1()
    version_2()

编辑:

我不确定这些线程是否可以使用 Qt 信号进行通信。他们可能需要使用 queue 进行通信,并且

Qt
可能需要
QTimer
定期检查
queue
中是否有新信息。

其他想法:

Flask
应该有
url
返回当前状态(连接或断开连接的信息)并且
Qt
可以使用
QTime
和可能的
QtNetwork.QNetworkRequest(QtCore.QUrl(url))
来检查此状态。这样您就可以随时使用其他 GUI 框架来检查状态。或者您可以在文本控制台中检查状态(即使用
curl
wget

如果您打算仅使用

Flask
来更改
Qt
中的状态,那么也许您应该使用
QtNetwork
直接在
Qt
中运行服务器,而不使用
Flask

© www.soinside.com 2019 - 2024. All rights reserved.