web-dev-qa-db-fra.com

Python: Ajout à la même liste à partir de différents processus utilisant le multitraitement

Je dois ajouter des objets à une liste "L" à partir de différents processus utilisant le multitraitement, mais la liste vide est renvoyée ..__ Comment puis-je laisser de nombreux processus s'ajouter à la liste "L" en utilisant le multitraitement?

    #!/usr/bin/python
from multiprocessing import Process
L=[]
def dothing(i,j):
        L.append("anything")
        print i
if __== "__main__":
        processes=[]
        for i in range(5):
                p=Process(target=dothing,args=(i,None))
                p.start()
                processes.append(p)
        for p in processes:
                p.join()
print L
6
Adam

Les variables globales ne sont pas partagées entre les processus.

Vous devez utiliser multiprocessing.Manager.list :

from multiprocessing import Process, Manager

def dothing(L, i):  # the managed list `L` passed explicitly.
    L.append("anything")

if __== "__main__":
    with Manager() as manager:
        L = manager.list()  # <-- can be shared between processes.
        processes = []
        for i in range(5):
            p = Process(target=dothing, args=(L,i))  # Passing the list
            p.start()
            processes.append(p)
        for p in processes:
            p.join()
        print L

Voir Etat de partage entre processus¶ (partie processus de serveur).

13
falsetru

Utiliser la solution fournie par @falsetru a fonctionné. mais la liste n'était toujours pas accessible au-delà de "with Manager() as manager:", deux modifications étaient nécessaires: 1.) en ajoutant "L = []" devant l'instruction "if __== "__main__": "

Doit être ajouté car, pour une raison quelconque, la dernière print(L) (celle "en dehors de" si ") tente d'être exécutée autant de fois qu'il y a de processus + 1?!?!?

cela renvoie une erreur indiquant que L n'est pas défini et que le code est cassé.

2.) ajout de "L = list(L)" après la déclaration "p.join()".

étape nécessaire pour changer Manager.list en Python.list normal - sinon, les appels au manager.list renvoient les erreurs qui ne sont pas lisibles.

####################
####### CODE: ######
####################

from multiprocessing import Process, Manager

def dothing(L, i):  # the managed list `L` passed explicitly.
    for j in range(5):
        text = "Process " + str(i) + ", Element " + str(j)
        L.append(text)

L = [] 

if __== "__main__":
    with Manager() as manager:
        L = manager.list()  # <-- can be shared between processes.
        processes = []

        for i in range(5):
            p = Process(target=dothing, args=(L,i,))  # Passing the list
            p.start()
            processes.append(p)

        for p in processes:
            p.join()

        L = list(L) 
        print("Within WITH")
        print(L)

    print("Within IF")
    print(L)

print("Outside of IF")
print(L)

"" "
##################### ###### OUTPUT: ##### #####################

Outside of IF
[]
Outside of IF
[]
Outside of IF
[]
Outside of IF
[]
Outside of IF
[]
Outside of IF
[]
Within WITH
['Process 2, Element 0', 'Process 2, Element 1', 'Process 2, Element 2',

'Processus 2, élément 3', 'Processus 2, élément 4', 'Processus 1, élément 0', 'Processus 1, élément 1', 'Processus 1, élément 2', 'Processus 1, élément 3' , 'Processus 1, élément 4', 'Processus 0, élément 0', 'Processus 0, élément 1', 'Processus 0, élément 2', 'Processus 0, Élément 3', 'Processus 0 , Élément 4 ', ' Processus 4, élément 0 ',' Processus 4, élément 1 ',' Processus 4, élément 2 ', ' Processus 4, élément 3 ',' Processus 4, élément 4 ' , 'Processus 3, élément 0', 'Processus 3, élément 1', 'Processus 3, élément 2', 'Processus 3, élément 3', 'Processus 3, élément 4']

Within IF
['Process 2, Element 0', 'Process 2, Element 1', 'Process 2, Element 2', 

'Processus 2, élément 3', 'Processus 2, élément 4', 'Processus 1, élément 0', 'Processus 1, élément 1', 'Processus 1, élément 2', 'Processus 1, élément 3' , 'Process 1, élément 4', 'Process 0, élément 0', 'Process 0, élément 1', 'Process 0, élément 2', 'Process 0, élément 3', 'Process 0 , Élément 4 ', ' Processus 4, élément 0 ',' Processus 4, élément 1 ',' Processus 4, élément 2 ', 'Processus 4, élément 3', 'Processus 4, élément 4', 'Processus 3, élément 0', 'Processus 3, élément 1', 'Processus 3, élément 2', 'Processus 3, élément 3' , 'Process 3, Element 4']

Outside of IF
['Process 2, Element 0', 'Process 2, Element 1', 'Process 2, Element 2', 

'Processus 2, élément 3', 'Processus 2, élément 4', 'Processus 1, élément 0', 'Processus 1, élément 1', 'Processus 1, élément 2', 'Processus 1, élément 3' , 'Processus 1, élément 4', 'Processus 0, élément 0', 'Processus 0, élément 1', 'Processus 0, élément 2', 'Processus 0, Élément 3', 'Processus 0 , Élément 4 ', ', Processus 4, élément 0 ',' processus 4, élément 1 ',' processus 4, élément 2 ', ' Processus 4, élément 3 ',' processus 4, élément 4 ' , 'Processus 3, élément 0', 'Processus 3, élément 1', 'Processus 3, élément 2', 'Processus 3, élément 3', 'Processus 3, élément 4']

"""
1
sebtac

Merci à @falsetru d'avoir suggéré la documentation exacte et d'avoir fourni le bon code. Je dois conserver la commande pour mon application et en modifiant le code @falsetru, le code ci-dessous préserve maintenant l'ordre d'ajout d'éléments à la liste. 

Le sommeil est utile pour attraper les bugs, sinon il est difficile d’attraper le problème avec la commande de la liste.

from multiprocessing import Process, Manager
from time import sleep

def dothing(L, i):  # the managed list `L` passed explicitly.
    L[i]= i
    sleep(4)

if __== "__main__":
    with Manager() as manager:
        L = manager.list(range(50))  # <-- can be shared between processes.
        processes = []
        for i in range(50):
            p = Process(target=dothing, args=(L,i))  # Passing the list
            p.start()
            processes.append(p)
        for p in processes:
            p.join()
        print(L)
0
Ehsan Sadr