Изменяет ли глобальное состояние Python `unittest.mock.patch`?

Я пытаюсь определить, изменяет ли контекстный менеджер Python mock.patch (unittest.mock.patch в Py3) глобальное состояние, то есть является ли он потокобезопасным.

Например: давайте представим, что один поток исправляет функцию bar внутри функции foo с помощью диспетчера контекста, а затем внутри диспетчера контекста интерпретатор приостанавливает этот поток (из-за GIL и т. д.) и возобновляет другой поток, который работает foo вне указанного диспетчера контекста. . Если patch является потокобезопасным, я ожидаю, что глобальное состояние функций foo и bar не изменится, и поэтому второй поток получит нормальное поведение foo. Но если patch изменяет глобальное состояние, второй поток получит измененное поведение foo, даже если он не находится внутри диспетчера контекста.

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


person Andrew Gorcester    schedule 11.11.2014    source источник


Ответы (2)


mock.patch по своей сути не является потокобезопасным или не потокобезопасным. Он изменяет объект. На самом деле это не что иное, как оператор присваивания в начале, а затем оператор присваивания отмены в конце.

Если к исправляемому объекту обращаются несколько потоков, то все потоки увидят изменение. Обычно он используется для изменения атрибутов модулей, которые являются глобальными. При таком использовании он не является потокобезопасным.

person Ned Batchelder    schedule 12.11.2014

Я пошел дальше и провел грубый эксперимент, используя multiprocessing.dummy.Pool на Python 3.4. В ходе эксперимента функция сопоставлялась с вводом диапазона (100) с использованием пула потоков, и если ввод функции был ровно 10, он исправлял внутреннюю функцию для вызова time.sleep(). Если бы патч был потокобезопасным, все результаты отображались бы немедленно, за исключением результата для 10, который отображался бы с опозданием; если бы он не был потокобезопасным, некоторые результаты отображались бы сразу, а многие другие появлялись бы с опозданием.

Результаты показали, что unittest.mock.patch изменяет глобальное состояние. Хорошо знать!

person Andrew Gorcester    schedule 12.11.2014