Flask semble empêcher la mise à jour de l'interface utilisateur de PyQt5.
Le code respectif fonctionne correctement pour PyQt5 ou Flask - mais pas ensemble. Je comprends que cela peut avoir à voir avec la façon dont le threading est configuré.
Toute aide serait grandement appréciée. TIA.
`
import sys import serial import threading from PyQt5.QtWidgets import QWidget, QLabel, QApplication from flask import Flask, render_template, request, redirect, url_for app1 = Flask(__name__) ser = serial.Serial ("/dev/ttyS0", 57600,timeout=3) #Open port with baud rate count=0 temp = [] class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): global count count = 1 self.setGeometry(300, 300, 250, 150) self.setWindowTitle('PyQt5 vs Flask') self.lbl1 = QLabel('Count '+str(count), self) self.lbl1.move(100, 50) self.show() threading.Timer(5,self.refresh).start() def refresh(self): global count count +=1 print("UI ",count) self.lbl1.setText('Count'+str(count)) threading.Timer(5,self.refresh).start() def get_uart(): global temp if ser.inWaiting()>0: temp =[str(float(x.decode('utf-8'))) for x in ser.read_until().split(b',')] print(temp) threading.Timer(1,get_uart).start() @app1.route("/") def index(): global temp templateData = {'temp1' : temp[1] ,'temp2' : temp[2]} return render_template('index.html',**templateData) if __name__ == "__main__": app = QApplication(sys.argv) pyqt5 = Example() threading.Timer(1,get_uart).start() ser.flushInput() #app1.run(host='0.0.0.0',threaded=True, port=5000) # ,debug=True) sys.exit(app.exec_())
`
Il faut une interface utilisateur pour contrôler l'analyse des données à afficher sur le site Web.
3 Réponses :
La meilleure façon de gérer les processus (éventuellement en attente) est d'utiliser les propres threads de Qt. Dans cet exemple, j'ai créé une sous-classe QObject qui effectue tout le traitement et envoie finalement un signal chaque fois que la condition est valide. Je ne peux pas installer flask pour le moment, donc je n'ai pas testé tout le code, mais vous aurez l'idée.
L'astuce consiste à utiliser un QObject "worker" qui effectue le traitement. Une fois que l'objet est créé, il est déplacé vers un nouveau QThread, où il effectue tout son traitement sans bloquer la boucle d'événements (donc, l'interface graphique). Vous pouvez également créer d'autres signaux pour cet objet et vous connecter à vos slots (qui peuvent également être des fonctions / méthodes python standard en dehors de QtApplication) qui seront appelées chaque fois que nécessaire.
class Counter(QtCore.QObject): changed = QtCore.pyqtSignal(str) def __init__(self): super().__init__() self.count = 0 def run(self): while True: self.thread().sleep(1) if ser.inWaiting() > 0: self.changed.emit('{}: {}'.format(self.count, [str(float(x.decode('utf-8'))) for x in ser.read_until().split(b',')])) self.count += 1 class Example(QtWidgets.QWidget): def __init__(self): super().__init__() self.counter = Counter() self.counterThread = QtCore.QThread() self.counter.moveToThread(self.counterThread) self.counterThread.started.connect(self.counter.run) self.initUI() def initUI(self): self.setGeometry(300, 300, 250, 150) self.setWindowTitle('PyQt5 vs Flask') self.lbl1 = QtWidgets.QLabel('Count {}'.format(self.counter.count), self) self.lbl1.move(100, 50) self.counter.changed.connect(self.lbl1.setText) self.counterThread.start() if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) pyqt5 = Example() pyqt5.show()
p >
Merci 'musicamante' d'avoir pris le temps de nous aider. J'explorerai votre solution plus en détail.
Je pense que le problème vient de la façon dont Flask est activé. Si la commande app.run reçoit des paramètres (même si dans un thread), cela bloque les autres commandes.
La seule façon dont j'ai pu faire fonctionner Flask et PyQt5 en même temps, était d'activer Flask dans un Thread dédié SANS aucun paramètre - VOIR CI-DESSOUS pour les différentes combinaisons.
Question: S'agit-il d'un bug ou d'une fonctionnalité Flask / Python ou d'une autre explication liée au déploiement de développement vs production?
Dans tous les cas, j'aimerais avoir de l'aide pour trouver un moyen de déployer flask dans un port autre que 5000 - SANS Flask Blocking autre code.
import sys import serial import threading import atexit from PyQt5.QtWidgets import QWidget, QLabel, QApplication from flask import Flask, render_template, request, redirect, url_for ser = serial.Serial ("/dev/ttyS0", 57600,timeout=3) #Open port with baud rate app = Flask(__name__) count=0 temp = [] class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): global count count = 1 self.setGeometry(300, 300, 250, 150) self.setWindowTitle('PyQt5 vs Flask') self.lbl1 = QLabel("Count "+str(count)+" ", self) self.lbl1.move(100, 50) self.show() threading.Timer(5,self.refresh).start() def refresh(self): global count global str_data count +=1 self.lbl1.setText("Count "+str(count)+" ") threading.Timer(0.5,self.refresh).start() def get_uart(): global temp if ser.inWaiting()>0: temp =[str(float(x.decode('utf-8'))) for x in ser.read_until().split(b',')] print(temp) threading.Timer(1,get_uart).start() @app.route("/") def blank(): global count data="Count "+str(count) return data if __name__ == "__main__": threading.Timer(5,get_uart).start() #app.run ## Does not block further execution. Website IS NOT available #app.run() ## Blocks further execution. Website available at port 5000 without Refresh value #app.run(port=5123) ## Blocks further execution. Website available at port 5123 without Refresh value #app.run(threaded=True) ## Blocks further execution. Website available at port 5000 without Refresh value #threading.Thread(target=app.run()).start() ## Blocks further execution. Website available at port 5000 without Refresh value #threading.Thread(target=app.run(port=5123)).start() ## Blocks further execution. Website available at port 5123 without Refresh value #threading.Thread(target=app.run(threaded=True)).start() ## Blocks further execution. Website available at port 5000 without Refresh value threading.Thread(target=app.run).start() ## Flask DOES NOT block. Website is available at port 5000 with Refresh value print("Flask does not block") app1 = QApplication(sys.argv) pyqt5 = Example() sys.exit(app1.exec_())
[RÉSOLU]
Tous les paramètres de Flask peuvent être définis comme:
port = int(os.environ.get('PORT', local_port)) kwargs = {'host': '127.0.0.1', 'port': port , 'threaded' : True, 'use_reloader': False, 'debug':False} threading.Thread(target=app.run, daemon = True, kwargs=kwargs).start()
et Flask ne se bloquera PAS et ne fonctionnera PAS avec les paramètres définis dans kwargs.
oh mec merci beaucoup ... C'était juste génial :) fonctionne parfaitement