简体   繁体   English

python的`unittest.mock.patch`是否会改变全局状态?

[英]Does python's `unittest.mock.patch` mutate global state?

I'm trying to determine if Python's mock.patch ( unittest.mock.patch in Py3) context manager mutates global state, ie, if it is thread-safe. 我试图确定Python的mock.patch (Py3中的unittest.mock.patch )上下文管理器是否会改变全局状态,即它是否是线程安全的。

For instance: let's imagine one thread patches function bar within function foo with a context manager, and then inside the context manager the interpreter pauses that thread (because of the GIL etc.) and resumes another thread, which runs foo outside of said context manager. 例如:让我们假设一个线程在函数foo使用上下文管理器修补函数bar ,然后在上下文管理器中,解释器暂停该线程(因为GIL等)并恢复另一个线程,该线程在所述上下文管理器之外运行foo If patch is thread-safe I would expect that the global state of the functions foo and bar are unmodified, and so the second thread will get the normal behavior of foo . 如果patch是线程安全的,我会期望函数foobar的全局状态是未修改的,因此第二个线程将获得foo的正常行为。 But if patch modifies global state, the second thread will get the modified behavior of foo even though it's not inside the context manager. 但是如果patch修改了全局状态,第二个线程将获得foo的修改行为,即使它不在上下文管理器中。

I referred to the source code but wasn't able to clearly tell just by looking at it. 我提到了源代码,但仅通过查看它就无法清楚地说出来。

mock.patch isn't inherently thread-safe or not thread-safe. mock.patch上不是线程安全的或不是线程安全的。 It modifies an object. 它修改了一个对象。 It's really nothing more than an assignment statement at the beginning, and then an undo-ing assignment statement at the end. 它只不过是一开始的赋值语句,最后是一个撤消赋值语句。

If the object being patched is accessed by multiple threads, then all the threads will see the change. 如果被修补的对象被多个线程访问,那么所有线程都将看到更改。 Typically, it's used to modify attributes of modules, which are global state. 通常,它用于修改模块的属性,这些属性是全局状态。 When used this way, it is not thread safe. 以这种方式使用时,它不是线程安全的。

I went ahead and ran a crude experiment using multiprocessing.dummy.Pool on Python 3.4. 我继续使用Python 3.4上的multiprocessing.dummy.Pool进行粗略的实验。 The experiment mapped a function against range(100) input using the thread pool, and if the input of the function was exactly 10, it patched an inner function to call time.sleep(). 实验使用线程池映射了一个针对range(100)输入的函数,如果函数的输入正好是10,它修补了一个内部函数来调用time.sleep()。 If the patch was threadsafe, the results would all show up immediately except for the result for 10, which would show up late; 如果补丁是线程安全的,结果将立即显示,除了10的结果,这将显示为晚; if it was not threadsafe, a few results would show up immediately and many others would show up late. 如果它不是线程安全的,那么会立即显示一些结果,而其他许多结果会显示得很晚。

The results demonstrated that unittest.mock.patch does mutate global state . 结果表明unittest.mock.patch 确实改变了全局状态 Good to know! 很高兴知道!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM