есть класс, который имеет много методов для обработки какой-то коллекции данных, схематически вот:
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. Правда, теперь для каждого метода будет инициализироваться сам класс. И вряд-ли можно сделать его синглтоном, ведь это всё пойдёт в отдельные процессы. Возможно, есть ещё какие-то варианты?