web-dev-qa-db-fra.com

Comment exécuter deux boucles Python simultanément?

Supposons que j'ai les éléments suivants en Python

# A loop
for i in range(10000):
    Do Task A

# B loop
for i in range(10000):
    Do Task B

Comment puis-je exécuter ces boucles simultanément en Python?

17
hiiii

Si vous voulez la concurrence, voici un exemple très simple:

from multiprocessing import Process

def loop_a():
    while 1:
        print("a")

def loop_b():
    while 1:
        print("b")

if __== '__main__':
    Process(target=loop_a).start()
    Process(target=loop_b).start()

Ceci est juste le exemple le plus fondamental auquel je pourrais penser. Assurez-vous de lire http://docs.python.org/library/multiprocessing.html pour comprendre ce qui se passe.

Si vous souhaitez renvoyer des données au programme, je vous recommande d'utiliser une file d'attente (qui, d'après mon expérience, est la plus simple à utiliser). 

Vous pouvez utiliser un fil à la place si vous ne vous souciez pas du verrou d'interprète global . Les processus sont plus coûteux à instancier, mais ils offrent une vraie concurrence.

23
Stefano Palazzo

Pourquoi voulez-vous exécuter les deux processus en même temps? Est-ce parce que vous pensez qu'ils iront plus vite (il y a de bonnes chances qu'ils ne le fassent pas). Pourquoi ne pas exécuter les tâches dans la même boucle, par exemple.

for i in range(10000):
    doTaskA()
    doTaskB()

La réponse évidente à votre question est d’utiliser des threads - voir le module python threading . Cependant, le filetage est un gros sujet et comporte de nombreux pièges, lisez-le avant de vous lancer dans cette voie. 

Sinon, vous pouvez exécuter les tâches dans des processus distincts, en utilisant le module python multiprocessing . Si les deux tâches consomment beaucoup de ressources en processeur, cela permettra de mieux utiliser plusieurs cœurs sur votre ordinateur.

Il existe d'autres options telles que des routines, des tâches sans pile, des greenlets, des CSP, etc., mais sans en savoir plus sur les tâches A et B et sur la raison pour laquelle elles doivent être exécutées en même temps, il est impossible de donner une réponse plus précise.

12
Dave Kirby

Il y a beaucoup d'options possibles pour ce que vous vouliez:

boucle d'utilisation

Comme beaucoup de gens l’ont souligné, c’est le moyen le plus simple.

for i in xrange(10000):
    # use xrange instead of range
    taskA()
    taskB()

Mérites: facile à comprendre et à utiliser, aucune bibliothèque supplémentaire nécessaire.

Inconvénients: taskB doit être effectué après taskA ou autrement. Ils ne peuvent pas fonctionner simultanément.

multiprocessus

Une autre idée serait: exécutez deux processus en même temps, Python fournit une bibliothèque multi-processus , voici un exemple simple:

from multiprocessing import Process


p1 = Process(target=taskA, args=(*args, **kwargs))
p2 = Process(target=taskB, args=(*args, **kwargs))

p1.start()
p2.start()

mérite: la tâche peut être exécutée simultaneously en arrière-plan, vous pouvez contrôler les tâches (les arrêter, les arrêter, etc.), les tâches peuvent échanger des données, peuvent être synchronisées si elles mettent en concurrence les mêmes ressources, etc.

inconvénients: trop lourd! Les systèmes d’exploitation basculent fréquemment entre eux, ils disposent de leur propre espace de données, même si les données sont redondantes. Si vous avez beaucoup de tâches (disons 100 ou plus), ce n'est pas ce que vous voulez. 

filetage

le filetage est comme un processus, juste léger. Découvrez ce post . Leur utilisation est assez similaire:

import threading 


p1 = threading.Thread(target=taskA, args=(*args, **kwargs))
p2 = threading.Thread(target=taskB, args=(*args, **kwargs))

p1.start()
p2.start()

coroutines

des bibliothèques telles que greenlet et gevent fournissent quelque chose appelé coroutines, censé être plus rapide que le threading. Aucun exemple fourni, s'il vous plaît google comment les utiliser si cela vous intéresse.

mérites: plus souple et léger

inconvénients: bibliothèque supplémentaire nécessaire, courbe d'apprentissage.

9
cizixs
from threading import Thread
def loopA():
    for i in range(10000):
        #Do task A
def loopB():
    for i in range(10000):
        #Do task B
threadA = Thread(target = loopA)
threadB = Thread(target = loobB)
threadA.run()
threadB.run()
# Do work indepedent of loopA and loopB 
threadA.join()
threadB.join()
7
Odomontois

Que diriez-vous: d'une boucle pour i dans la plage (10000): effectuez la tâche A, effectuez-vous la tâche B? Sans plus d'informations, je n'ai pas de meilleure réponse.

1
PeterK

Vous pouvez utiliser threading ou multitraitement .

1
Matt Curtis

Je trouve que l'utilisation du sous-module "pool" dans "multitraitement" fonctionne à merveille pour l'exécution de plusieurs processus simultanément dans un script Python.

Voir section: Utilisation d'un bassin de travailleurs

Regardez attentivement "# lancer plusieurs évaluations de manière asynchrone may utiliser plus de processus" dans l'exemple. Une fois que vous avez compris ce que font ces lignes, l’exemple suivant que j’ai construit aura beaucoup de sens.

import numpy as np
from multiprocessing import Pool

def desired_function(option, processes, data, etc...):
    # your code will go here. option allows you to make choices within your script
    # to execute desired sections of code for each pool or subprocess.

    return result_array   # "for example"


result_array = np.zeros("some shape")  # This is normally populated by 1 loop, lets try 4.
processes = 4
pool = Pool(processes=processes)
args = (processes, data, etc...)    # Arguments to be passed into desired function.

multiple_results = []
for i in range(processes):          # Executes each pool w/ option (1-4 in this case).
    multiple_results.append(pool.apply_async(param_process, (i+1,)+args)) # Syncs each.

results = np.array(res.get() for res in multiple_results)  # Retrieves results after
                                                           # every pool is finished!

for i in range(processes):
    result_array = result_array + results[i]  # Combines all datasets!

Le code exécutera la fonction souhaitée pour un nombre défini de processus. Vous devrez vous assurer avec soin que votre fonction peut faire la distinction entre chaque processus (d'où la raison pour laquelle j'ai ajouté la variable "option".) De plus, il ne doit pas nécessairement s'agir d'un tableau qui est rempli à la fin, mais pour mon exemple, c'est comme ça que je l'ai utilisé. J'espère que cela simplifie ou vous aide à mieux comprendre la puissance du multitraitement en Python!

0