Python 3: перехват предупреждений во время многопроцессорной обработки

Too long; didn't read

warnings.catch_warnings() контекстный менеджерне безопасно, Как я могу использовать его в среде параллельной обработки?

Background

Приведенный ниже код решает проблему максимизации с использованием параллельной обработки с использованием Python.multiprocessing модуль. Он принимает список (неизменяемых) виджетов, разбивает их на части (см.Эффективная многопроцессорная обработка массивной максимизации грубой силы в Python 3), находит максимумы («финалисты») всех разделов, а затем находит максимум («чемпион») этих «финалистов». Если я правильно понимаю свой собственный код (и я не буду здесь, если бы я это сделал), я делюсь памятью со всеми дочерними процессами, чтобы предоставить им входные виджеты, иmultiprocessing использует канал на уровне операционной системы и выборку для отправки виджетов финалиста обратно в основной процесс, когда рабочие закончили.

Source of the problem

I want to catch the redundant widget warnings being caused by widgets' re-instantiation after the unpickling это происходит, когда виджеты выходят из межпроцессного канала. Когда объекты виджета создаются, они проверяют свои собственные данные, выдавая предупреждения из стандарта Pythonwarnings модуль, чтобы сообщить пользователю приложения, что виджет подозревает, что существует проблема с входными данными пользователя. Поскольку удаление объектов приводит к созданию экземпляров объектов, мое понимание кода подразумевает, что каждый объект виджета повторно создается только один раз, если и только если он является финалистом после того, как он выходит из конвейера - см. Следующий раздел, чтобы понять, почему это не правильно ,

Виджеты уже были созданы до того, как их фробниковали, поэтому пользователь уже мучительно осознает, какой ввод он ошибся, и не хочет слышать об этом снова. Это предупреждения, которые я хотел бы узнать с помощьюwarnings Модуль & APOS; scatch_warnings() менеджер контекста (т.е.with заявление).

Failed solutions

В моих тестах я сужался, когда излишние предупреждения посылаются в любое место между тем, что я обозначил ниже какLine A а такжеLine B, Что меня удивляет, так это то, что предупреждения раздаются в других местах, кромеoutput_queue.get(), Это подразумевает для меня, чтоmultiprocessing отправляет виджеты рабочим, используя травление.

Результатом является то, что положить контекстный менеджер, созданныйwarnings.catch_warnings() даже вокруг всего отLine A вLine B и установка правильного фильтра предупреждений в этом контексте не перехватывает предупреждения. Это подразумевает для меня, что предупреждения передаются в рабочих процессах. Размещение этого менеджера контекста вокруг рабочего кода также не перехватывает предупреждений.

The code

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

"Call `frobnicate(list_of_widgets)` to get the widget with the most frobnals"

def frobnicate_parallel_worker(widgets, output_queue):
    resultant_widget = max(widgets, key=my_frobnal_counter)
    output_queue.put(resultant_widget)

def frobnicate_parallel(widgets):
    output_queue = multiprocessing.Queue()
    # partitions: Generator yielding tuples of sets
    partitions = my_load_balancer(widgets)
    processes = []
    # Line A: Possible start of where the warnings are coming from.
    for partition in partitions:
        p = multiprocessing.Process(
                 target=frobnicate_parallel_worker,
                 args=(partition, output_queue))
        processes.append(p)
        p.start()
    finalists = []
    for p in processes:
        finalists.append(output_queue.get())
    # Avoid deadlocks in Unix by draining queue before joining processes
    for p in processes:
        p.join()
    # Line B: Warnings no longer possible after here.
    return max(finalists, key=my_frobnal_counter)

Ответы на вопрос(2)

Ваш ответ на вопрос