Comment puis-je utiliser le filetage en Python?
J'essaie de comprendre le filetage en Python. J'ai regardé la documentation et des exemples, mais franchement, de nombreux exemples sont trop sophistiquées et je vais avoir du mal à les comprendre.
Comment voulez-vous montrer clairement les tâches étant réparties pour le multi-threading?
- Une bonne discussion générale autour de ce sujet peuvent être trouvées dans Python Problème très difficile par Jeff Knupp. En résumé, il semble que le filetage n'est pas pour les débutants.
- haha, j'ai tendance à penser que le filetage est pour tout le monde, mais les débutants ne sont pas de filetage :)))))
- Juste pour signaler que les gens devraient lire toutes les réponses que plus tard sont sans doute mieux que les nouvelles fonctionnalités de langage sont mis à profit...
- N'oubliez pas d'écrire votre logique de base en C et les appeler par l'intermédiaire de ctypes à vraiment prendre avantage de Python threading.
- Je voulais juste ajouter que PyPubSub est un excellent moyen d'envoyer et de recevoir des messages de contrôle de flux de Fil
- Ce type de question doit également avoir la "valeur historique" encore "pas une bonne DONC question de type" avertissement sur elle
Vous devez vous connecter pour publier un commentaire.
Depuis que cette question a été posée en 2010, il y a eu une réelle simplification dans la façon de faire simple multithreading avec Python avec carte et piscine.
Le code ci-dessous provient d'un article/billet de blog que vous devriez certainement vérifier (pas d'affiliation) - Le parallélisme en une ligne: Un Meilleur Modèle pour le quotidien le Filetage des Tâches. Je vais résumer ci-dessous -, il finit par être juste quelques lignes de code:
Qui est la version multithread:
Description
Mise en œuvre
multiprocessing.dummy
est exactement le même que le multitraitement module, mais utilise des threads au lieu (une distinction importante - utiliser plusieurs processus pour les tâches consommatrices d'UC; les fils (et pendant) I/O):Et le calendrier résultats:
Passer plusieurs arguments (fonctionne comme ceci seulement en Python 3.3 et versions ultérieures):
Pour passer plusieurs tableaux:
Ou de passer d'une constante et d'un tableau:
Si vous utilisez une version antérieure de Python, vous pouvez passer plusieurs arguments via cette solution de contournement).
(Grâce à user136036 pour le commentaire.)
with Pool(8) as p: p.map( *whatever* )
et de se débarrasser de la comptabilité lignes de trop.results.append(my_function(item))
au lieu deresults += my_function(item)
? Je voudrais également mettreresults = []
au début de préciser que les résultats d'une liste; comme il est, ça ressemble à des résultats est un nombre.results = []
mais ne serait pas le.append()
effectivement ajouter des listes, au lieu de l'étendre? stackoverflow.com/a/252711/2327328.append()
agit de l'ajout d'un élément à une liste;+=
est pour la concaténation d'une liste à la fin de l'autre. Essayez-la dans l'interpréteur.spam = []; spam += 5
entraîne une erreur, maisspam.append(5)
fonctionne très bien.map
n'a pas cette supposition. Par conséquent, les deux morceaux de code sont pas est équivalent.pool.map(any_function, iterable)
pool.close()
pool.terminate()
.from multiprocessing.dummy import Pool as ThreadPool
, iciPool
est importé en tant qu'aliasThreadPool
, mais danswith
, comment vous êtes capable de fairewith Pool(4) as pool:
, ce doit être une erreur!!!urls = [ numpy.random.random((5000000, 1)), numpy.random.random((5000000, 1)), numpy.random.random((5000000, 1)), numpy.random.random((5000000, 1)) ]; result = pool.map(sum, urls)
(il doit être enveloppé dans def_main), et retirez-la .mannequin__main__
. Peut-être il peut travailler à l'intérieur d'une fonction, n'ont pas le testfunction
soulève une exception, comment gérer un comportement non bloquant?Voici un exemple simple: vous avez besoin d'essayer un peu d'autres adresses Url et renvoie le contenu de la première à répondre.
C'est un cas où le filetage est utilisé comme un simple optimisation: chaque subthread est en attente d'une URL pour résoudre et répondre, pour mettre son contenu dans la file d'attente; chaque thread est un démon (ne pas garder le processus de suivi si le thread principal se termine -- plus fréquent); le thread principal commence, toutes les sous-parties, une
get
sur la file d'attente à attendre jusqu'à ce que l'un d'eux a fait unput
, puis émet les résultats et se termine (ce qui met à mal toutes les sous-parties qui pourraient encore être en cours d'exécution, car ils sont les fils de démon).Bonne utilisation des threads en Python est invariablement liés à des opérations d'e/S (Disponible depuis ne pas utiliser plusieurs cœurs pour exécuter le CPU des tâches de toute façon, la seule raison pour le filetage n'est pas le blocage du processus alors qu'il y a une attente pour certains I/O). Les files d'attente sont presque toujours le meilleur moyen de farm le travail des fils et/ou de collecter les résultats du travail accompli, par la manière, et ils sont intrinsèquement des threads, de sorte qu'ils vous sauver de se soucier de serrures, les conditions, les événements, les sémaphores, et d'autres inter-thread coordination/concepts de communication.
join()
méthode, puisque cela rendrait le thread principal d'attendre jusqu'à ce qu'ils ont fait, sans consommer de processeur constamment à la vérification de la valeur. @Alex: merci, c'est exactement ce dont j'avais besoin pour comprendre comment utiliser les threads.Queue
nom du module avecqueue
. Nom de la méthode est la même.s = q.get()
print s
@krs013 Vous n'avez pas besoin de lajoin
parce que la File d'attente.get() est bloquant.Queue.get([block[, timeout]])
. Il devrait donc êtreQueue.get(True)
afin de blocage. Sourceblock
estTrue
par défaut, de sorte que la File d'attente.get() est blocage. Source: le très-vous cité 😉concurrent.futures.as_completed
(stdlib dans Py3.2 et meilleur, pypi backport pour les précédentes versions de Python).NOTE: Pour réelle la parallélisation en Python, vous devez utiliser le multitraitement module de la fourche à la fourchette de multiples processus qui s'exécutent en parallèle (en raison du blocage de l'interpreteur global, Python fils de fournir de l'entrelacement, mais ils sont en fait exécutées en série, non pas en parallèle, et ne sont utiles que si l'entrelacement des opérations d'e/S).
Toutefois, si vous êtes simplement à la recherche pour l'entrelacement (ou faire des opérations d'e/S peut être parallélisée malgré le blocage de l'interpreteur global), puis le filetage module est l'endroit pour commencer. Comme vraiment un exemple simple, considérons le problème de l'addition d'une large gamme en additionnant les sous-plages en parallèle:
Remarque que ci-dessus est un très stupide exemple, comme il ne fait absolument aucun I/O et seront exécutées en série mais entrelacés (avec la charge supplémentaire de la commutation de contexte) dans Disponible fait de la mondialisation de l'interprète de verrouillage.
thread1
s'exécute jusqu'à la fin alors que le thread principal blocs, la même chose se produit avecthread2
, alors le thread principal reprend et imprime les valeurs qu'ils ont accumulés.super(SummingThread, self).__init__()
? Comme dans stackoverflow.com/a/2197625/806988thread1 = threading.Thread(target=function_name, args=(arg1, arg2, ...))
et de la fonction de travail défini à l'avance. Il fait threads one-liner définitions au lieu de devoir créer une classe entière.Comme d'autres l'ont mentionné, Disponible pouvez utiliser les threads uniquement pour les e/S d'attente dues à GIL.
Si vous voulez bénéficier de plusieurs cœurs de CPU des tâches, l'utilisation multitraitement:
f
fonction. En parallèle, le programme principal maintenant, juste attend pour le processus de sortie,join
ing en place avec elle. Si la partie principale juste de sortir, le sous-processus pourrait ou ne pourrait pas exécuter jusqu'à la fin, donc en faisant unjoin
est toujours recommandé.map
fonction est ici: stackoverflow.com/a/28463266/2327328Juste une remarque: Une file d'attente n'est pas nécessaire pour l'enfilage.
C'est l'exemple le plus simple que j'ai pu imaginer que la montre 10 processus qui s'exécutent simultanément.
for
boucle, vous pouvez appelerthread.start()
dans la première boucle.La réponse d'Alex Martelli m'a aidé. Cependant, voici une version modifiée que je pensais était plus utile (au moins pour moi).
Mise à jour: fonctionne dans les deux Python 2 et Python 3
import Queue ModuleNotFoundError: No module named 'Queue'
je suis en cours d'exécution python 3.6.5 certains postes de mentionner que dans python 3.6.5 il estqueue
mais, même après que je l'ai changer, ne fonctionne toujours pasJ'ai trouvé cela très utile: créer autant de threads que de cœurs et de les laisser exécuter un (grand) nombre de tâches (dans ce cas, l'appel d'un programme shell):
Donné une fonction,
f
, c'est le fil comme ceci:Pour passer des arguments à
f
Thread
objet nettoie. Voir la doc. Il y a unis_alive()
méthode que vous pouvez utiliser pour vérifier un thread si vous en avez besoin.is_alive
méthode, mais je ne pouvais pas comprendre comment l'appliquer sur le fil. J'ai essayé l'attributionthread1=threading.Thread(target=f).start()
et puis en vérifiant avecthread1.is_alive()
, maisthread1
est rempli avecNone
, donc pas de chance là-bas. Savez-vous si il existe un autre moyen pour accéder à la discussion?thread1=threading.Thread(target=f)
suivie parthread1.start()
. Ensuite, vous pouvez fairethread1.is_alive()
.thread1.is_alive()
retourneFalse
dès que la fonction se termine.Python 3 a de la facilité de le lancement de tâches en parallèle. Cela rend notre travail plus facile.
Il a mise en pool de threads et processus de mise en commun.
La suite donne un aperçu:
ThreadPoolExecutor Exemple (source)
ProcessPoolExecutor (source)
À l'aide de l'explorant de nouveaux de façon concomitante.les contrats à terme module
L'exécuteur approche peut sembler familier à tous ceux qui ont obtenu leur main à la pâte avec du Java avant.
Également sur une note de côté: Pour garder l'univers sain d'esprit, n'oubliez pas de fermer vos pools/exécuteurs si vous n'utilisez pas
with
contexte (qui est tellement génial qu'il le fait pour vous)Pour moi, l'exemple parfait pour le filetage est de la surveillance des événements asynchrones. Regardez ce code.
Vous pouvez jouer avec ce code par l'ouverture d'un IPython session et de faire quelque chose comme:
Attendre quelques minutes
La plupart de la documentation et des tutoriels utiliser Python
Threading
etQueue
module, et qu'ils pouvaient sembler écrasante pour les débutants.Peut-être envisager la
concurrent.futures.ThreadPoolExecutor
module de Python 3.Combiné avec
with
de la clause et de la compréhension de liste cela pourrait être un réel charme.J'ai vu beaucoup d'exemples ici où aucun véritable travail a été effectué, et ils étaient pour la plupart par le CPU. Voici un exemple d'un CPU tâche qui calcule tous les nombres premiers compris entre 10 millions et 10,05 millions de dollars. J'ai utilisé toutes les quatre méthodes ici:
Voici le résultat sur mon Mac OS X quatre-core de la machine
if __name__ == '__main__':
avant l'appel principal, sinon la mesure de l'auto-génère et imprime Une tentative a été faite pour démarrer un nouveau processus avant....Ici est l'exemple très simple de CSV importer à l'aide du filetage. (Bibliothèque d'inclusion peuvent être différents pour des fins différentes.)
Des Fonctions D'Assistance:
Fonction De Pilote:
Ici est multi threading avec un exemple simple qui peut être utile. Vous pouvez l'exécuter et de comprendre facilement comment multi threading est de travailler en Python. J'ai utilisé un verrou pour empêcher l'accès à d'autres threads jusqu'à ce que la précédente threads terminé leur travail. Par l'utilisation de cette ligne de code,
vous pouvez permettre à un certain nombre de processus à la fois et garder le reste des fils qui se déroulera plus tard, ou après avoir terminé le processus précédents.
Je voudrais contribuer avec un exemple simple et les explications que j'ai trouvé utile lorsque j'ai eu à faire face à ce problème moi-même.
Dans cette réponse, vous trouverez quelques informations sur Python GIL (global interprète de verrouillage) et une simple journée-à-jour exemple écrites à l'aide de multitraitement.mannequin plus simple de repères.
Mondiale Interprète de Verrouillage (GIL)
Python ne permet pas le multi-threading dans le vrai sens du mot. Il dispose d'un multi-threading, mais si vous voulez multi-thread à la vitesse de votre code, alors il n'est généralement pas une bonne idée de l'utiliser.
Python ont une construction appelée le mondial interprète de verrouillage (GIL).
Le GIL permet de s'assurer qu'un seul de vos tâches peuvent s'exécuter à un moment donné. Un thread acquiert le GIL, fait un peu de travail, puis passe le GIL sur le fil suivant.
Cela se produit très rapidement, de sorte que l'oeil humain, il peut sembler comme votre threads s'exécutent en parallèle, mais ils sont vraiment juste de prendre les virages en utilisant le même PROCESSEUR core.
Tout cela GIL passant ajoute de la surcharge à l'exécution. Cela signifie que si vous voulez faire de votre code de courir plus vite à l'aide de l'enfilage
package n'est pas souvent une bonne idée.
Il y a des raisons d'utiliser Python thread du paquet. Si vous souhaitez exécuter certaines choses en même temps, et l'efficacité n'est pas un problème,
alors il est tout à fait bien et pratique. Ou si vous exécutez le code qui doit attendre quelque chose (comme d'I/O), alors il pourrait faire beaucoup de sens. Mais le filetage de la bibliothèque ne vous laissent pas utiliser supplémentaire de cœurs.
Multi-threading peut être sous-traités par le système d'exploitation (en faisant multi-processing), et d'application externe qui appelle votre code Python (par exemple, Spark ou Hadoop), ou un peu de code que votre code Python appels (par exemple: vous pourriez avoir votre code Python appeler une fonction C qui ne le coûteux multi-thread trucs).
Pourquoi Est-Ce Important
Parce que beaucoup de gens passent beaucoup de temps à essayer de trouver les goulots d'étranglement dans leur fantaisie Python multi-threaded code avant d'apprendre que le GIL est.
Une fois que cette information est claire, voici mon code:
Aucune des solutions précédentes effectivement utilisé plusieurs cœurs sur mon GNU/Linux server (où je n'ai pas les droits administrateur). Ils ont juste couru sur un seul core.
J'ai utilisé le niveau inférieur
os.fork
interface pour frayer les multiples processus. C'est le code qui a fonctionné pour moi:Avec emprunt de ce post nous savons sur le choix entre le multithreading, le multitraitement et async/
asyncio
et de leur utilisation.Python 3 a une nouvelle bibliothèque intégrée dans l'ordre de la simultanéité et de parallélisme: de façon concomitante.les contrats à terme
Donc je vais démontrer par une expérience de quatre tâches (c'est à dire
.sleep()
méthode) parThreading-Pool
manière:De sortie:
[NOTE]:
multiprocessing
vsthreading
) vous pouvez changer laThreadPoolExecutor
àProcessPoolExecutor
.