Pour moi, c'est en fait assez simple:
subprocess
est pour l'exécution d'autres exécutables --- en gros, c'est un wrapper autour de os.fork()
et os.execve()
, avec un certain soutien pour l'option de plomberie (installation de Tuyaux et de la sous-processus. (Évidemment, d'autres systèmes de communication inter-processus (IPC) des mécanismes, tels que les sockets, SysV de la mémoire partagée et les files d'attente peuvent être utilisés --- mais en général, vous êtes à l'aide de sous-processus à exécuter tiers exécutables binaires et vont être coincé avec les interfaces et les canaux IPC ceux à l'appui).
Généralement on utilise subprocess
de façon synchrone --- il suffit d'appeler certains utilitaire externe et de la lecture du son en sortie ou en attente de sa réalisation (peut-être la lecture de ses résultats à partir d'un fichier temporaire, ou après affichée sur son site à une base de données). Cependant, on peut pondre des centaines de sous-processus et de sondage. Mon propre favori utilitaire est exactement ce que fait. Le plus grand inconvénient de l' subprocess
module, c'est que son support e/S est généralement de blocage. Il y a le projet PEP-3145 le corriger dans une version future de Python 3.x et une alternative asyncproc (Avertissement qui mène droit à la télécharger, et non à toute sorte de documentation, ni README). J'ai trouvé aussi qu'il est relativement facile de simplement importer fcntl
et de manipuler votre Popen
PIPE descripteurs de fichiers directement --- si je ne sais pas si c'est portable pour non-plates-formes UNIX.
subprocess
a presque pas de la gestion des événements de soutien ... si vous pouvez utiliser l' signal
module et la plaine de la vieille école UNIX/Linux signaux de --- tuant vos processus doucement, comme elle l'avait fait.
multiprocessing
est pour l'exécution de fonctions au sein de votre existant (Python) code avec support pour plus de souplesse de communication au sein de la famille de processus. En particulier, il est préférable de construire votre multiprocessing
de la CIB à travers le module de l' Queue
objets, si possible, mais vous pouvez également utiliser Event
objets et d'autres caractéristiques différentes (dont certaines sont, sans doute, construit autour d' mmap
appui sur les plates-formes qui prennent en charge est suffisante).
Python multiprocessing
module est destiné à fournir des interfaces et des fonctionnalités qui sont très similaires à threading
tout en permettant Disponible à l'échelle de votre traitement entre plusieurs Processeurs/cœurs en dépit de la GIL. Il tire parti de toutes les fines SMP de verrouillage et la cohérence de l'effort qui a été fait par les développeurs de votre noyau de système d'exploitation.
threading
est pour une fourchette relativement étroite de demandes d'e/S lié (n'avez pas besoin d'échelle sur plusieurs cœurs de PROCESSEUR) et qui bénéficient de la très faible latence de commutation et les frais généraux de fil de commutation (avec socle commun de mémoire) vs processus/changement de contexte. Sur Linux c'est presque l'ensemble vide (Linux processus de temps de commutation sont extrêmement proche de son fil-interrupteurs).
threading
souffre de deux inconvénients majeurs en Python. L'un, bien sûr, est la mise en œuvre spécifique --- affectant principalement Disponible. C'est le GIL (Global Interprète de Verrouillage). Pour la plupart, la plupart Disponible programmes ne bénéficient pas de la disponibilité de plus de deux Processeurs (noyaux) et, souvent, les performances vont souffrir de la GIL conflits de verrouillage. Le plus grand problème qui n'est pas mise en œuvre spécifique, est que les threads partagent le même espace mémoire, les gestionnaires de signaux, les descripteurs de fichier et de certains autres systèmes d'exploitation des ressources. Ainsi, le programmeur doit être extrêmement prudent au sujet de l'objet de verrouillage, la gestion des exceptions et d'autres aspects de leur code qui sont à la fois subtils et qui peut tuer, de décrochage, ou de blocage de l'ensemble du processus (suite de threads).
Par contre, l' multiprocessing
modèle donne à chaque processus de sa propre mémoire, les descripteurs de fichier, etc. D'un crash ou d'une exception non gérée dans l'un d'entre eux ne tuent que des ressources et robuste de la manipulation de la disparition d'un enfant, frère ou sœur processus peut être beaucoup plus facile que de débogage, d'isoler et de fixation ou de travailler autour des questions similaires dans les threads.
- (Note: l'utilisation d'
threading
avec de grandes Python systèmes, tels que Numpy, peuvent souffrir de considérablement moins de GIL contention de la plupart de votre propre code Python serait. C'est parce qu'ils ont été spécialement conçues pour le faire).
Il est également intéressant de noter que Tordu offre encore une autre alternative qui est à la fois élégante et très difficile à comprendre. En gros, au risque de trop simplifier, au point où les fans de Torsadée peut tempête de ma maison avec des fourches et des torches, Tordu offre événementielle et coopérative multi-tâches à l'intérieur de tout (unique).
Pour comprendre comment cela est possible, on devrait lire sur les caractéristiques de l' select()
(ce qui peut être construit autour de la select() ou poll() ou similaire OS appels système). Fondamentalement, c'est tous animés par la capacité à effectuer une demande de l'OS de sommeil dans l'attente d'une activité sur une liste de descripteurs de fichiers ou de dépassement du temps. L'éveil de chacun de ces appels à l' select()
est un événement soit un impliquant d'entrée disponibles (lisible) sur un certain nombre de sockets ou des descripteurs de fichiers, ou de mise en mémoire tampon de l'espace devient disponible sur certains autres descripteurs ou des prises (en écriture), ou de certaines conditions exceptionnelles (TCP out-of-band POUSSER avais des paquets, par exemple), ou un DÉLAI d'attente.
Ainsi, le Tordu modèle de programmation est construite autour de la gestion de ces événements alors en boucle sur la "main" de gestionnaire, lui permettant d'envoyer les événements de vos gestionnaires.
Personnellement, je pense que de le nom, Tordu comme évocatrice du modèle de programmation ... depuis votre approche du problème doit être, dans un certain sens, "tordu" à l'intérieur. Plutôt que de concevoir votre programme comme une série d'opérations sur les données d'entrée et de sorties ou de résultats, vous écrivez votre programme en tant que service ou démon et de définir comment il réagit à divers événements. (En fait, le noyau principal de la boucle" Tordue d'un programme (généralement? toujours?) un reactor()
.
Les principaux défis liés à l'utilisation Tordu impliquer la torsion de votre esprit autour de l'événement piloté par le modèle et aussi renonçant à l'utilisation de bibliothèques de classes ou de trousses à outils qui ne sont pas écrites à co-opérer à l'intérieur de la torsion du cadre. C'est pourquoi Tordu fournit ses propres modules pour la gestion du protocole SSH, pour les malédictions, et de son propre sous-processus/popen fonctions, et de nombreux autres modules et les gestionnaires de protocole qui, à première vue, semble dupliquer les choses dans les bibliothèques standard Python.
Je pense qu'il est utile de comprendre Tordu sur un plan conceptuel, même si vous n'avez jamais l'intention de l'utiliser. Il peut donner un aperçu de la performance, la contention et la gestion des événements dans votre threading, le multitraitement et même des sous-processus de manutention ainsi que tout traitement distribué, vous vous engagez.
Encore un autre domaine de traitement, vous n'avez pas demandé à ce sujet, mais qui est à considérer, c'est que des distribué de traitement. Il existe de nombreux outils Python et de cadres pour la distribution de traitement et de calcul parallèle. Personnellement, je pense que le plus facile à utiliser est celui qui est le moins souvent considéré comme étant dans l'espace.
Il est presque banal de construire de traitement distribué autour de Redis. L'ensemble de magasin de clés peuvent être utilisés pour stocker les unités de travail et les résultats, Redis Listes peuvent être utilisées comme Queue()
comme objet, et de la PUB/SUB support peut être utilisé pour Event
-comme de la manipulation. Vous pouvez hachage vos clés et valeurs d'usage, répliqué sur une lâche la grappe de Redis cas, pour stocker de la topologie et de hachage-jeton de mappages d'assurer l'uniformité des fonctions de hachage et de basculement pour une mise à l'échelle au-delà de la capacité d'une seule instance de coordination de vos travailleurs et de regroupement de données (marinés, JSON, BFILS, ou YAML) d'entre eux.
Bien sûr, comme vous commencez à construire une échelle plus grande et la plus sophistiquée de la solution autour Redis, vous re-mettre en œuvre plusieurs fonctionnalités qui ont déjà été résolus par l'utilisation d'Hadoop, Zookeeper, Cassandra et ainsi de suite. Ceux-ci sont des modules de Python d'accès à leurs services.
Là, vous avez toute la gamme de possibilités de traitement de Python, de mono-thread, avec de simples appels synchrones pour les sous-processus, les piscines de sondés sous-processus, threads et de multitraitement, événementiel d'coopérative multi-tâches, et pour le traitement distribué.