IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Gestion du Multithreading avec PyQt5


Sujet :

Python

  1. #1
    Membre confirmé
    Inscrit en
    Avril 2004
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 97
    Par défaut Gestion du Multithreading avec PyQt5
    Bonjour,
    J'utilise Python 3.10 et PyQt5
    Je suis en train de développer une interface pour piloter différents moyens (caméra, platine de translation, platine de rotation...).
    Tout ces moyens sont connecté en USB, Ethernet et RS232 pour certain.
    Dans mon IHM, j'ai besoin d'afficher l'image de ma caméra toutes les secondes et réguliérement rafraichir le status de tous les équipements connectés.
    Le pilotage des équipements se fait de maniére asynchrone.
    Tout cela sans que l'IHM ne se freeze.

    Par conséquent, j'ai besoin d'utiliser des Threads.
    Pour le rafraichissement de l'image de la caméra, j'allais utiliser la fonction QTImer, avec son interval de temps pour gérer cela.
    Est il possible de lancer 2 QTimer ? (1 pour ma caméra et 1 pour le rafraichissement des status)

    Ensuite les autres équipements, j'ai besoin de faire du multithreading.
    Il y aura un bouton de connexion afin d'établir la lien.
    Ensuite différent bouton pour les piloter.
    Mais j'aimerai également, que mes équipements soient capables de mettre d'afficher des données dans mon IHM.
    et que mon IHM puisse lui envoyer des données.

    Exemple:
    1 bouton => connexion à ma platine de rotation
    j'ai un champ texte pour indiquer l'angle dont j'ai besoin
    Un bouton "GO" pour lancer la rotation
    J'ai un QTableWidget qui me permet d'afficher tout le log de mes activités (dans l'exemple il va afficher lancement de la rotation, et afficher la fin de la rotation)
    J'ai une fonction FillLogbook qui permet de remplir ce log mais également d'enregistrer le log en temps réel. Donc quand l'action du thread est lancé, il faut que le thread appel cette fonction pour afficher mais aussi pour sauvegarder le log au bon endroit.
    C'est un des exemples d'intéraction que je dois gérer.

    Auriez vous un exemple ou un bon tuto de gestion de thread pour mon probléme?

    Merci d'avance
    Julien

  2. #2
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 322
    Par défaut
    bonjour
    Citation Envoyé par astragoth Voir le message
    PyQt5
    Mais pourquoi qt5 pour un nouveau projet ? La seule raison qui me vient a l'esprit est que tu désires programmer une obsolescence assez rapidement.
    De plus il y a des nouvelles fonctionnalités et modules dans Qt6 (qui a déjà pas mal d'années : 5 ans)

    Auriez vous un exemple ou un bon tuto de gestion de thread pour mon probléme?
    De ce que tu expliques, je ne suis pas sûr que thread soit obligatoire, tu ne nous donnes aucun traitement lourd ici.

    Lancer 2 timeurs ? Si tu désires en lancer 36, c'est ok, c'est la moindre des choses avec un framework évènementiel.

    Sinon tu as commencé par la doc j'espère ?
    QtAsyncio est sans doute bien suffisant ? depuis Qt 6.6 !
    - https://doc.qt.io/qtforpython-6/PySi...cio/index.html
    - https://doc.qt.io/qtforpython-6/exam...c_minimal.html
    - https://doc.qt.io/qtforpython-6/exam...c-eratosthenes

    Pour QThread, on trouve que 10 000 exemples sur le web
    - https://doc.qt.io/qtforpython-6/PySi...read.html#more
    - https://doc.qt.io/qtforpython-6/exam...uneclient.html
    - https://www.pythonguis.com/tutorials...s-qthreadpool/
    $moi= (:nono: !== :oops:) ? :king: : :triste: ;

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par astragoth Voir le message
    Auriez vous un exemple ou un bon tuto de gestion de thread pour mon probléme?
    Si ça existe, on les trouve sur Internet avec son moteur de recherche. Les mots clefs "pyqt5, threading" sont assez simple à trouver. Sûr que vous allez en trouver des tas.
    Un qui va me plaire ne vous plaira pas du tout et réciproquement: nous avons des attentes différentes et aussi des savoirs différents.
    A vous de prendre le temps de lire/trier/approfondir le sujet et de revenir avec des questions plus précises.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 827
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Citation Envoyé par astragoth Voir le message
    J'utilise Python 3.10 et PyQt5
    Pour un nouveau projet c'est bien dommage. PyQt6 est sorti il y a presque 5 ans et PySide6, qui est son miroir, t'offrira la possibilité de laisser ton projet en version propriétaire (obligé de mettre ton projet en version GPL avec PyQt). Et les deux fonctionnent sous P310.

    Citation Envoyé par astragoth Voir le message
    Est il possible de lancer 2 QTimer ? (1 pour ma caméra et 1 pour le rafraichissement des status)
    Oui pas de souci. Te suffit d'affecter le timeout de chaque QTimer à des slots dédiés.
    Un exemple de QTimer ici: https://qt.developpez.com/telecharge...7284/It-s-time.

    Citation Envoyé par astragoth Voir le message
    Auriez vous un exemple ou un bon tuto de gestion de thread pour mon probléme?
    La base de la compréhension, c'est qu'un QThread n'a absolument pas le droit d'interagir directement avec Qt. Si tu fais ça, c'est le crash.
    Donc il faut que ton thread émette des signaux qui seront récupérés par un élément de base Qt et c'est cet élément qui pourra agir sur l'IHM.
    Exemple ici: https://qt.developpez.com/telecharge...ad-de-tyrtamos. Et pour lui comme pour l'autre, tu les trouveras en version PyQt5, PyQt6 et PySide6.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 060
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 060
    Par défaut
    Hello,

    PyQt5 est largement suffisant pour ce projet. La nouvelle feature QtAsyncIO me semble pas particulièrement adapté à ton cas et ne nécessite donc pas le passage de PyQt5 à PyQt6, je dirai même que ça peut ajouter des difficultés supplémentaires.

    De plus, certains retours indiquent même des régressions potentielles de performance initiales avec Qt6 par rapport à Qt5 sur certaines plateformes ou applications... mais beaucoup annoncent aussi des avantages à passer à Qt6, cependant est-ce important de se poser cette question pour un projet perso ? Je ne pense pas, dans certains des projets historiques actuels en entreprise, on est en python 2.7, est-ce que ça pose des problèmes de fonctionnalités ? Non !

    L'argument selon lequel QThread ne serait utile que pour le "traitement lourd" (CPU-bound) est une mauvaise interprétation (j'ai déjà cette discussion avec @wiztricks pensant à tort cela, et comme souvent il avait raison). QThread est essentiel pour toute tâche susceptible de bloquer le thread GUI, ce qui inclut fondamentalement les tâches liées aux E/S qui passent du temps en attente. L'objectif premier ici n'est pas d'exploiter le parallélisme de calcul (limité en Python par le Global Interpreter Lock - GIL), mais de maintenir la réactivité de l'IHM en déplaçant l'attente bloquante hors du thread principal.

    Le GIL a d'ailleurs moins d'impact sur les tâches I/O-bound, car un thread attendant une E/S externe libère généralement le GIL, permettant à d'autres threads (comme le thread GUI) de s'exécuter.

    L'intention d'utiliser QTimer pour les rafraîchissements périodiques (image caméra, statuts) est tout à fait appropriée. QTimer fonctionne au sein de la boucle d'événements Qt. Il est parfaitement valide de lancer plusieurs instances de QTimer. Si la tâche déclenchée par le timeout du QTimer est elle-même bloquante (par exemple, la lecture directe de l'image ou du statut prend du temps), alors le slot connecté au timeout ne devrait pas effectuer l'opération bloquante directement. Il devrait plutôt émettre un signal connecté à un slot d'un Worker dans un QThread pour effectuer l'opération bloquante en arrière-plan.

    L'application doit communiquer avec du matériel via USB, Ethernet et RS232. Les bibliothèques Python couramment utilisées pour ces interfaces (par exemple, pyserial pour le port série, d'autres pour l'USB ou des protocoles Ethernet spécifiques) sont souvent synchrones et bloquantes. Je ne vois donc pas l'intérêt de l'approche asynchrone pour ce cas de figure... mais on peut cependant, la complexité qu'on ajoutera dessus se rapprochera de l'utilisation de QThread.

    Pour une réponse au PO, ça a déjà été donné par @wiztricks
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    QThread est essentiel pour toute tâche susceptible de bloquer le thread GUI, ce qui inclut fondamentalement les tâches liées aux E/S qui passent du temps en attente.
    Avec l'adaptation de pas mal de bibliothèques qui effectuent des ES à asyncio, on ne devrait même pas avoir besoin de threads dans ce cas là (pourvu qu'on sache faire coexister les 2 mainloops). Je n'ai pas regardé mais il y a certainement des qui ont testé pour savoir s'il y a des avantages ou pas.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 322
    Par défaut
    "lourd" en effet ne veut pas dire grand-chose.
    Dans mon IHM, j'ai besoin d'afficher l'image de ma caméra toutes les secondes et régulièrement rafraichir le status de tous les équipements connectés.
    Comme ecrit plus haut, je ne vois rien de bien lourd ... Ici, je ne vois qu'une unique caméra à afficher et un "petit" update dans l'interface du status de la caméra.

    Status de la caméra : nous sommes en événementiel, donc l'événement "update" ou qui va déclencher l'update d'une partie de la GUI sera traité par QT lorsqu'il aura le temps et ne sera donc aucunement bloquant.
    J'ai une fonction FillLogbook qui permet de remplir ce log mais également d'enregistrer le log en temps réel.
    C'est donc 2 petites fonctions distinctes ? "send événement" pour QTableWidget et "send événement" "écriture d'une ligne dans un fichier ?", pas de quoi bloquer la gui.

    Reste donc que l'affichage de la caméra qui pour moi n'est pas forcément un traitement lourd ou bloquant.
    Dans la doc, nous avons un exemple de caméra sans aucun thread

    --------------------

    Citation Envoyé par astragoth Voir le message
    Le pilotage des équipements se fait de maniére asynchrone.
    @fred1599 Voila pourquoi j'ai parlé de asyncio. Si astragoth utilise déjà peut-être qu'il préfère utiliser (ou pas). Ce n'est pas à nous de dire qu'il faut ou pas utiliser, que c'est compliqué ou non Par contre, l'informer que cela est possible avec QT est certainement une bonne chose.
    $moi= (:nono: !== :oops:) ? :king: : :triste: ;

  8. #8
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 060
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 060
    Par défaut
    Citation Envoyé par wiztricks
    Avec l'adaptation de pas mal de bibliothèques qui effectuent des ES à asyncio, on ne devrait même pas avoir besoin de threads dans ce cas là (pourvu qu'on sache faire coexister les 2 mainloops). Je n'ai pas regardé mais il y a certainement des qui ont testé pour savoir s'il y a des avantages ou pas.
    Il existe des efforts pour créer des équivalents asynchrones (comme pyserial-asyncio ), mais leur disponibilité, leur maturité ou leur compatibilité multiplateforme ne sont pas toujours garanties pour tous les cas d'usage. Si une seule bibliothèque essentielle reste bloquante, l'utilisation directe d'asyncio pour cette partie devient problématique car elle bloquerait la boucle d'événements asyncio.
    La solution serait alors d'utiliser run_in_executor, ce qui réintroduit l'utilisation de threads.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

Discussions similaires

  1. Réponses: 1
    Dernier message: 28/04/2024, 17h29
  2. Class de gestion des images avec rotation
    Par Johnny Boy dans le forum MFC
    Réponses: 1
    Dernier message: 03/05/2005, 11h54
  3. Gestion de formulaire avec xml et sans serveur ?
    Par meliane dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 05/05/2004, 19h57
  4. probleme de gestion de clients avec des sockets....
    Par ludvo dans le forum Réseau
    Réponses: 6
    Dernier message: 25/09/2003, 12h37
  5. [TFrame] Problème de gestion du OnMouseDown avec une Frame
    Par xherault dans le forum Composants VCL
    Réponses: 5
    Dernier message: 23/05/2003, 15h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo