138 votes

Le filetage dans un PyQt application: l'Utilisation de Qt fils ou Python fils?

Je suis en train d'écrire une application graphique qui télécharge régulièrement des données via une connexion web. Depuis cette recherche prend du temps, ce qui provoque l'INTERFACE utilisateur ne répond pas pendant le processus de récupération (il ne peut pas être divisé en parties plus petites). C'est pourquoi je tiens à externaliser la connexion par le web à un autre thread.

[Oui, je sais, maintenant, j'ai deux problèmes.]

De toute façon, l'application utilise PyQt4, donc j'aimerais savoir ce que le meilleur choix est: l'Utilisation de Qt fils ou utiliser le Python threading module? Quels sont les avantages / inconvénients de chacun? Ou avez-vous une autre suggestion?

Edit (re bounty): Alors que la solution dans mon cas particulier sera probablement à l'aide d'un non-blocage de la demande de réseau comme Jeff Ober et Lukáš Lalinský suggéré (donc en gros, en laissant les problèmes de simultanéité de la mise en réseau mise en œuvre), je voudrais encore un peu plus en profondeur, de répondre à la question générale:

Quels sont les avantages et les inconvénients de l'utilisation de PyQt4 (Qt) les threads natifs Python threads (à partir de l' threading module)?


Edit 2: Merci à tous pour vous réponses. Bien qu'il n'y a pas 100% d'accord, il semble y avoir un consensus général que la réponse est "l'utilisation de Qt", puisque l'avantage est que l'intégration avec le reste de la bibliothèque, tout en ne provoquant pas d'inconvénients réels.

Pour ceux qui cherchent à choisir entre les deux threading implémentations, j'ai fortement recommandé de lire toutes les réponses fournies ici, y compris le PyQt liste de diffusion thread que l'abbé de liens.

Il y avait plusieurs réponses que j'ai retenus pour la générosité; à la fin, j'ai choisi de l'abbé de la très pertinente de référence externe; il était, cependant, un appel à proximité.

Merci encore.

121voto

abbot Points 8093

Cela a été discuté il y a pas longtemps en PyQt liste de diffusion. Citant Giovanni Bajo de commentaires sur le sujet:

C'est essentiellement le même. La principale différence est que QThreads sont mieux intégré avec Qt (asynchrnous signaux/slots, boucle d'événements, etc.). Aussi, vous ne pouvez pas utiliser Qt à partir d'un Python fil (vous ne pouvez pas par exemple post-événement pour le thread principal par le biais de QApplication.postEvent): vous besoin d'un QThread pour que cela fonctionne.

Une règle générale de pouce pourrait être d'utiliser QThreads si vous allez interagir d'une certaine manière avec Qt et Python, utiliser les threads autrement.

Et certains commentaire précédent sur ce sujet à partir de PyQt de l'auteur: "ils sont tous les deux des wrappers autour du même thread natif implémentations". Et les deux implémentations utilisent GIL de la même manière.

38voto

Jeff Ober Points 3314

Python fils sera plus simple et plus sûr, et comme c'est pour un I/O-en fonction de l'application, ils sont en mesure de contourner le GIL. Cela dit, avez-vous envisagé de non-blocage I/O à l'aide de Tordu ou de non-blocage des sockets/select?

EDIT: de plus sur les threads

Python fils

Python threads threads du système. Cependant, Python utilise un mondial interprète de verrouillage (GIL) pour s'assurer que l'interprète n'est jamais que de l'exécution d'une certaine taille de bloc de byte-code d'instructions à la fois. Heureusement, Python publie le GIL pendant les opérations d'entrée/sortie, faire des threads utile pour simuler des non-blocage I/O.

Mise en garde importante: Cela peut être trompeur, puisque le nombre de byte-code des instructions ne pas correspondre au nombre de lignes dans un programme. Même une seule assignation ne peut être atomique en Python, donc un mutex lock est nécessaire pour tout bloc de code qui doit être exécuté de façon atomique, même avec le GIL.

QT fils

Quand Python mains hors de contrôle à une 3ème partie module compilé, il publie le GIL. Il est de la responsabilité du module afin d'assurer l'atomicité si nécessaire. Lorsqu'une commande est passée, Python va utiliser le GIL. Cela peut rendre l'utilisation de la 3e partie des bibliothèques en collaboration avec des fils à confusion. Il est encore plus difficile d'utiliser un filetage extérieur de la bibliothèque, car cela ajoute à l'incertitude quant à l'endroit et au moment où le contrôle est dans les mains du module vs l'interprète.

QT threads fonctionnent avec le GIL libéré. QT threads sont en mesure d'exécuter la bibliothèque QT de code (et d'autres compilé le module de code qui n'a pas acquis le GIL) simultanément. Toutefois, le code Python exécutée dans le contexte d'un QT thread toujours acquiert le GIL, et maintenant vous avez à gérer les deux jeux de logique pour le verrouillage de votre code.

En fin de compte, à la fois QT threads Python et les threads sont des wrappers autour de threads du système. Python threads sont légèrement plus sûrs à utiliser, car les parties qui ne sont pas écrit en Python (implicitement à l'aide de la GIL) utiliser le GIL dans tous les cas (même si la mise en garde ci-dessus s'applique toujours.)

Non-blocage I/O

Threads ajouter de l'extraordinaire complexité de votre demande. Surtout lorsqu'il s'agit déjà complexe de l'interaction entre l'interpréteur Python et compilé le code du module. Alors que de nombreux trouver l'événement de programmation basé difficile à suivre, événement, non-blocage I/O est souvent beaucoup plus difficile à comprendre que les threads.

Avec les e/S asynchrones, vous pouvez toujours être sûr que, pour chaque descripteur ouvert, le chemin d'exécution est cohérente et ordonnée. Il y a, évidemment, des questions qui doivent être abordées, telles que que faire lorsque le code suivant sur un canal à ciel ouvert de plus amples dépend des résultats du code pour être appelée lorsqu'un autre canal ouvert renvoie des données.

Une solution sympa pour de l'événementiel, de non-blocage I/O est le nouveau Diesel de la bibliothèque. Il est limité à Linux pour le moment, mais il est extrêmement rapide et très élégant.

Il est également utile de votre temps pour apprendre pyevent, un wrapper autour de la magnifique libevent de la bibliothèque, qui fournit un cadre de base pour l'événement de base de la programmation à l'aide de la manière la plus rapide de méthode disponible pour votre système (déterminé au moment de la compilation).

22voto

Lukáš Lalinský Points 22537

L'avantage de l' QThread c'est qu'il est intégré avec le reste de la bibliothèque Qt. C'est, fil-connaissance des méthodes de Qt aurez besoin de savoir dans quel thread qu'ils exécutent, et de déplacer des objets entre les threads, vous devez utiliser QThread. Une autre fonctionnalité utile est la gestion de votre propre boucle d'événement dans un thread.

Si vous accédez à un serveur HTTP, vous devriez envisager QNetworkAccessManager.

15voto

Natim Points 4393

Je me suis posé la même question quand je travaillais à PyTalk.

Si vous êtes à l'aide de Qt, vous devez utiliser QThread à être en mesure d'utiliser le framework Qt et spécialement le rapport signal/slot système.

Avec le rapport signal/slot moteur, vous serez en mesure de parler à partir d'un thread à l'autre et à chaque partie de votre projet.

En outre, il n'est pas très performance question à propos de ce choix, puisque ce sont deux C++ liaisons.

Voici mon expérience de PyQt et du fil.

Je vous encourage à utiliser QThread.

9voto

Kaleb Pederson Points 22428

Jeff a quelques bons points. Un seul thread principal peut faire toute la GUI mises à jour. Si vous avez besoin de mettre à jour l'interface graphique depuis le thread, Qt-4 de la file d'attente de raccordement des signaux de faire, il est facile d'envoyer des données entre threads et sera automatiquement engagée si vous utilisez QThread; je ne sais pas si ils seront si vous êtes à l'aide de Python fils, bien qu'il est facile d'ajouter un paramètre à l' connect().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X