Многопроцессорность и dict пусты после обновления [python3]

у меня есть одна проблема с моим кодом в python3: я пробовал много решений, но все равно тот же результат.

import pprint
import concurrent
import multiprocessing
from concurrent import futures

class exempleStackOverFlow: 
    def __init__(self):
        self.dict1={}
        self.headers = {"header1","header2","header3"}

    def fillIn(self,key):
        response = {key:{'first':['1','2','3']}}
        self.dict1.update(response)
        pprint.pprint(response)

e =  exempleStackOverFlow()

def try_my_operation(item):
    try:
        e.fillIn(item)      
    except:
        print('error with item')

executor = concurrent.futures.ProcessPoolExecutor(2)
futures = [executor.submit(try_my_operation, item) for item in e.headers]
concurrent.futures.wait(futures)
print(e.dict1)

Результат

{'header3': {'first': ['1', '2', '3']}}
{'header1': {'first': ['1', '2', '3']}}
{'header2': {'first': ['1', '2', '3']}}
{}

Ожидается

 {'header3': {'first': ['1', '2', '3']}}
 {'header1': {'first': ['1', '2', '3']}}
 {'header2': {'first': ['1', '2', '3']}}
 {'header1': {'first': ['1', '2', '3']},
'header2': {'first': ['1', '2', '3']},
     'header3': {'first': ['1', '2', '3']}}

(или какой бы то ни было порядок заголовков)

Возможно, я не понял, как это работает, я хотел бы немного пролить свет на мою проблему, пожалуйста, dict1 пуст в конце, когда я ввожу try_my_operation.

он хорошо обновляется без многопроцессорной/одновременной обработки (например, если я делаю e.fillIn("headers1"),e.fillIn("headers2")... и после того, как я могу получить полный dict1.

Спасибо за любые будущие комментарии


person M1n1M1n1ng    schedule 29.09.2017    source источник
comment
Вы создаете 2 процесса поверх одного основного процесса. Ваш результат ожидается от вашего кода. Идея состоит в том, чтобы получить ваш текущий результат, а также распечатать все три, добавленные вместе из self.dict1.update?   -  person Treyten Carey    schedule 29.09.2017
comment
Спасибо за ваш ответ, это просто результат печати для отслеживания изменений. в результате мой возвращенный dict пуст {} вместо того, что я хотел бы в «ожидаемом», что означает self.dict1 equal to {'header1': {'first': ['1', '2', '3']}, 'header2': {'first': ['1', '2', '3']}, 'header3': {'first': ['1', '2', '3']}} вместо self.dict1 равно {}   -  person M1n1M1n1ng    schedule 29.09.2017
comment
Смотрите мой ответ ниже   -  person Treyten Carey    schedule 29.09.2017


Ответы (2)


Я полагаю, вы ищете ThreadPoolExecutor, а не ProcessPoolExecutor.

Здесь я использую многопоточность (без параллельного выполнения), чтобы получить ожидаемый результат:

import pprint
from threading import Thread

class exempleStackOverFlow: 
    def __init__(self):
        self.dict1={}
        self.headers = ["header1","header2","header3"]

    def fillIn(self,key):
        response = {key:{'first':['1','2','3']}}
        self.dict1.update(response)
        pprint.pprint(response)

def try_my_operation(item):
    try:
        e.fillIn(item)
    except:
        print('error with item')

e =  exempleStackOverFlow()

for i in range(len(e.headers)):
    futures = Thread(target = try_my_operation, args = (e.headers[i],));
    futures.start();
    futures.join();

print(e.dict1)

Разница в том, что e в многопроцессорной обработке не является общим объектом, поэтому e не обновляется между всеми процессами. В многопоточности они используют одни и те же переменные, поэтому e можно обновлять, как и ожидалось.

Изменить:

Я не знаком с concurrent, но уверен, что у него есть метод, аналогичный совместному использованию типов и объектов, таких как многопроцессорность показана здесь и объекты, использующие менеджеры, подобные здесь.

Если скорость — это то, что вы ищете, обязательно выберите маршрут многопроцессорности и поделитесь своим объектом с помощью менеджера, такого как from multiprocessing.managers import BaseManager.

person Treyten Carey    schedule 29.09.2017
comment
Еще раз здравствуйте, спасибо за ответ, теперь он работает, но я потерял всю скорость по сравнению с предыдущим методом? Любое предположение? - person M1n1M1n1ng; 29.09.2017
comment
Ага. Потоки не предлагают улучшения скорости в python. Смотрите редактирование моего ответа. - person Treyten Carey; 29.09.2017
comment
да, скорость - единственная цель, хорошо, я посмотрю BaseManager! Я скоро вернусь, чтобы дать ответ на этот пост. Спасибо за ваше время - person M1n1M1n1ng; 29.09.2017

с помощью @Treyten Care

Нужно добавить к моему начальному сообщению:

from multiprocessing import Process, Manager 

class exempleStackOverFlow: 
        def __init__(self):
            manager = Manager()
            self.dict1 = manager.dict()

С этим я могу обновить свой дикт. Благодарить

person M1n1M1n1ng    schedule 29.09.2017