Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 3, 2017 19:24:59

Master_Sergius
Зарегистрирован: 2013-09-12
Сообщения: 271
Репутация: +  7  -
Профиль   Отправить e-mail  

multiprocessing.Pool и методы екземпляра класса

Здравствуйте. Вот такая интересная задачка, над которой уже второй день сижу (Python 2.7.13):
есть класс, который имеет много методов для обработки какой-то коллекции данных, схематически вот:

 class DataProcessor(object):
    def process1(self, data):
         print "process 1 finished"
         return data
 
   def process2(self, data):
         print "process 2 finished"
         return data
   def process3(self, data):
         print "process 3 finished"
         return data
 
   def process4(self, data):
         print "process 4 finished"
         return data
 
   def make_all_processes(self, data):
        processes = [getattr(self, method) for method in dir(self) if method.startswith('process')]
        results = [process(data) for process in processes]
        return results

Вот эти процессы обработки данных хочу распаралелить, наибольший выигрыш получился через отдельные процессы, вот приблизительно таким образом:

 results = multiprocessing.Manager().dict()                             
processes = []                                                           
for lookup in lookup_methods:                                          
    process = multiprocessing.Process(target=self._lookup_process_wrapper, args=(lookup, input_data, results))
    process.start()                                                     
    processes.append(process)                                             
                                                                                 
for process in processes:                                                 
    process.join()

Естественно, если таких методов будет много, а у меня их сейчас 6, то куда разумней создать пул процессов, а не порождать новый процесс на каждый метод. И вот как раз с этим проблемы - в пул нельзя запихнуть метод экземпляра класса, так как они не могут быть сериализированы. Через multiprocessing.Queue или multiprocessing.Manager - то же самое.
Как же элегантно решить данную проблему?

п.с. есть ещё один вариант, поскольку всю сборку мне надо отобразить на веб-странице, возможно попробовать создать на каждый метод свой ajax-запрос, но не уверен, что это хорошее решение. Тем более, что такое паралельное выполнение может пригодиться где-то ещё.


Дополнение 1
Решил проблему таким образом:

  def lookup_process_wrapper(lookups_queue, data, results, config_dict):                             
    while True:                                                                 
         try:                                                                    
             lookup = lookups_queue.pop()                                        
         except:                                                                 
             break                                                               
         data_processor = DataProcessor(config_dict)                 
         lookup_method = getattr(data_processor, lookup)                              
         results[lookup] = lookup_method(data=data)

Эта функция объявлена на уровне модуля, она сериализируется и принимает в качестве аргументов только сериализируемые значения. Тогда её можно использовать в multiprocessing.Pool не изменяя сам класс DataProcessor. Правда, теперь для каждого метода будет инициализироваться сам класс. И вряд-ли можно сделать его синглтоном, ведь это всё пойдёт в отдельные процессы. Возможно, есть ещё какие-то варианты?



———————————————————————————
Мой блог о семействе *nix: http://nixtravelling.blogspot.com/

Отредактировано Master_Sergius (Авг. 4, 2017 13:52:13)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version