Многопроцессорная обработка Python "не может расслаиваться" при использовании ведения журнала - PullRequest
1 голос
/ 07 ноября 2019

Я использую multiprocessing.Pool для распараллеливания некоторого кода Python, который я написал для симуляции (боя в D & D 5e). Однако я получаю эту ошибку: can't pickle _thread.RLock objects. Я провел некоторое исследование, и похоже, проблема в том, что в моем моделировании используются объекты, которые имеют регистраторы (из модуля logging). Я все еще хотел бы поддерживать ведение журнала для однопроцессных прогонов моделирования (чтобы люди могли выполнять отладку / проверку выходных данных), но поддержка ведения журнала для запусков нескольких процессов для меня менее важна, поскольку, как только пользователь узнает, что моделирование работает правильно, оникак правило, не нужно играть за игрой. Как я могу реорганизовать мой код так, чтобы регистрация здесь не была проблемой (отключение ведения журнала при наличии нескольких процессов, реализация ведения журнала способом, который принимает многопроцессорная обработка, или что-то еще)?

Некоторый код из моего класса Simulation:

    def process_run(self, num):  # pylint: disable=unused-argument
        """
        The method given to an individual process to do work. Run only once per process so we don't need to reset anything

        :param num: which iteration of the loop am I
        :return:
        """
        self._encounter.run()
        return self._encounter.get_stats()

    def mp_run(self, n=1000, p=None):
        """
        Run the Encounter n times (using multiprocessing), then print the results
        :param n: number of times to run the encounter
        :param p: number of processes to use. If None, use max number of processes
        :return: aggregate stats
        """
        if p:
            pool = Pool(p)  # use user-specified number of processes
        else:
            pool = Pool()  # use max number of processes as user didn't specify
        for result in pool.imap_unordered(self.process_run, range(n)):
            self.update_stats(result)
        pool.close()
        pool.join()
        self.calculate_aggregate_stats(n)
        self.print_aggregate_stats()
        return self._aggregate_stats

Некоторый код, который использует журналирование (из класса Encounter, экземпляром которого является каждое моделирование):

            self.get_logger().info("Round %d", self.get_round())
            unconscious = [comb.get_name() for comb in self.get_combatants() if comb.has_condition("unconscious")]
            if unconscious:
                self.get_logger().info("Unconscious: %s", str(unconscious))
            dead = [comb.get_name() for comb in self.get_combatants() if comb.has_condition("dead")]
            if dead:
                self.get_logger().info("Dead: %s", str(dead))

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

...