Как использовать многопроцессорность в Python на объекте класса

Я довольно новичок в Python, и мой опыт связан с его использованием в моделировании Powerflow через API, предоставляемый в Siemens PSS/e. У меня есть сценарий, который я использую в течение нескольких лет, который запускает некоторое моделирование на большом наборе данных.

Чтобы быстро закончить, я обычно делю входные данные на несколько частей, а затем запускаю несколько экземпляров сценария в IDLE. Недавно я добавил графический интерфейс для входных данных и усовершенствовал код, чтобы он был более объектно-ориентированным, создав класс, в который графический интерфейс передает входные данные, но затем работает как оригинальный скрипт.

Мой вопрос: как мне разделить процесс внутри самой программы, а не делать несколько копий? Я немного прочитал о модуле mutliprocess, но я не уверен, как применить его к моей ситуации. По сути, я хочу иметь возможность создать N номер одного и того же объекта, каждый из которых работает параллельно.

Класс, который у меня сейчас (называется Bot), получает набор аргументов и создает вывод csv, пока он работает, пока не завершится. У меня есть отдельный блок кода, который собирает кусочки в конце, но сейчас мне просто нужно понять лучший подход к запуску нескольких объектов Bot после того, как я нажал run в моем GUI. Есть входы в GUI, чтобы указать количество N сегментов, которые будут использоваться.

Я заранее прошу прощения, если мой вопрос довольно расплывчатый. Спасибо за любую информацию, так как я как бы застрял и не знаю, где искать лучшие ответы.

2 ответа

Создайте список конфигураций:

configurations = [...]

Создайте функцию, которая принимает соответствующую конфигурацию и использует ваши Bot:

def function(configuration):
    bot = Bot(configuration)
    bot.create_csv()

Создать Pool из работников с любым количеством процессоров, которые вы хотите использовать:

from multiprocessing import Pool
pool = Pool(3)

Вызовите функцию несколько раз, что каждая конфигурация в вашем списке конфигураций.

pool.map(function, configurations)

Например:

from multiprocessing import Pool
import os

class Bot:
    def __init__(self, inputs):
        self.inputs = inputs

    def create_csv(self):
        pid = os.getpid()
        print('TODO: create csv in process {} using {}'
              .format(pid, self.inputs))


def use_bot(inputs):
     bot = Bot(inputs)
     bot.create_csv()


def main():
    configurations = [
        ['input1_1.txt', 'input1_2.txt'],
        ['input2_1.txt', 'input2_2.txt'],
        ['input3_1.txt', 'input3_2.txt']]

    pool = Pool(2)
    pool.map(use_bot, configurations)

if __name__ == '__main__':
    main()

Выход:

TODO: create csv in process 10964 using ['input2_1.txt', 'input2_2.txt']
TODO: create csv in process 8616 using ['input1_1.txt', 'input1_2.txt']
TODO: create csv in process 8616 using ['input3_1.txt', 'input3_2.txt']

Если вы хотите сделать жизнь немного менее сложной, вы можете использовать multiprocess вместо multiprocessing, так как есть лучшая поддержка для классов, а также для работы в переводчике. Как вы можете видеть ниже, теперь мы можем напрямую работать с методом в экземпляре класса, что невозможно с multiprocessing,

>>> from multiprocess import Pool
>>> import os
>>> 
>>> class Bot(object):
...   def __init__(self, x): 
...     self.x = x
...   def doit(self, y):
...     pid = os.getpid()
...     return (pid, self.x + y)
... 
>>> p = Pool()
>>> b = Bot(5)
>>> results = p.imap(b.doit, range(4))
>>> print dict(results)
{46552: 7, 46553: 8, 46550: 5, 46551: 6}
>>> p.close()
>>> p.join()

Выше, я использую imap, чтобы получить итератор результатов, который я просто добавлю в dict, Обратите внимание, что вы должны закрыть свои бассейны после того, как вы сделали, чтобы очистить. В Windows вы также можете посмотреть на freeze_support, для случаев, когда в противном случае код не запускается.

>>> import multiprocess as mp
>>> mp.freeze_support 
Другие вопросы по тегам