Как защитить Python многопроцессорность на Windows от нежелательной рекурсии - PullRequest
0 голосов
/ 17 апреля 2020

Итак, я делаю этот проект, в котором выполняются следующие шаги (обязательно такие, какие они есть):

  • Программа алгоритма оптимизации (пакет O) вызывает скрипт анализа самолета в качестве подпроцесса;
  • Сценарий анализа летательного аппарата (сценарий S) вызывает пакет аэродинамики;
  • Пакет анализа летательного аппарата (назовем его пакетом P) создает несколько многопроцессорных экземпляров класса Process для распараллеливания тяжелых задач.

На Linux это работает без каких-либо проблем.

На Windows, однако, пакету P требуется защита, не позволяющая дочерним процессам рекурсивно повторно импортировать свой сценарий отца S (как в python многопроцессорная обработка на Windows), что приводит к бесконечно повторяющемуся выполнению задачи.

Нетрудно реализовать его, добавив защиту к сценарию S:

if __name__=='__main__':
    #do stuff, call methods from package P

Я не хотел, чтобы мои пользователи использовали этот сторож при каждом обращении к пакету, поэтому вместо этого я добавил сторож к пакету P. Он реализован в виде флага, как в (имена, отредактированные для простоты, пакет имеет более 5000 строк):

class FirstClass:
    #first method in package P to be executed in script S is FirstClass.__init__
    def __init__(self):
        self.ischild=(multiprocessing.current_process().name != 'MainProcess')
    def some_other_method(self):
        if not self.ischild:
            do_stuff_that_the_package_should_do()

Таким образом, по сути, функции и методы пакета P запускаются, только если установлен флаг ischild установлен в False в первом классе, созданном сценарием S.

Он работает, когда сценарий S вызывается из командной строки, и останавливает сценарий S от выполнения каких-либо действий в дочернем процессе, поскольку он реимпортируется - следовательно, останавливает оба избыточные задачи и создание рекурсивного подпроцесса.

Когда я пытаюсь настроить пакет оптимизации O для запуска сценария S в качестве подпроцесса, однако, эта защита перестает работать, поскольку сценарий S больше не является основным процессом. Флаг ischild, таким образом, устанавливается в True, даже когда скрипт S запускается впервые пакетом O, потому что multiprocessing.current_process().name больше не равен 'MainProcess', даже если вызов не рекурсивный.

Есть ли какой-нибудь другой способ, которым я могу реализовать Guard для пакета P, чтобы остановить его рекурсивные вызовы основного процесса, который работал бы, даже если скрипт S не является основным процессом?

Это было бы было бы хорошо, если бы я мог точно определить, какой пакет / скрипт вызвал процесс, с помощью чего-то вроде:

if multiprocessing.father()=='package_P':
    ischild=True #stops execution of function do_stuff_the_package_should_do() when the call is recursive

, чтобы не возникало никаких проблем, когда вызывающий процесс не является ни основным процессом (как это было бы, если бы сценарий S является подпроцессом другого сценария или пакета), а также дочерним процессом из пакета P (рекурсивный вызов).

1 Ответ

1 голос
/ 17 апреля 2020

Просто проведите рефакторинг вашего кода таким образом, чтобы при импорте S не происходила неявная автоматическая многопроцессорная обработка.

Например,

S/
  __init__.py
  __main__.py

, где только S/__main__.py запускается независимо от того, что вы делает. Затем вы можете запустить python -m S и Python вызовет этот основной модуль. Простой импорт S (или что-нибудь из S) не сделает этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...