4

我正在尝试确定 Python 的mock.patchunittest.mock.patch在 Py3 中)上下文管理器是否会改变全局状态,即它是否是线程安全的。

例如:让我们想象一个线程使用上下文管理器在函数bar内修补函数foo,然后在上下文管理器内部,解释器暂停该线程(由于 GIL 等)并恢复另一个foo在所述上下文管理器之外运行的线程。如果patch是线程安全的,我希望函数的全局状态foobar未修改,因此第二个线程将获得foo. 但是如果patch修改全局状态,第二个线程将获得修改后的行为,foo即使它不在上下文管理器中。

我参考了源代码,但仅通过查看无法清楚地分辨出来。

4

2 回答 2

10

mock.patch本质上不是线程安全的或不是线程安全的。它修改一个对象。它实际上只不过是开头的赋值语句,然后是结尾的撤消赋值语句。

如果被修补的对象被多个线程访问,那么所有线程都会看到变化。通常,它用于修改模块的属性,即全局状态。以这种方式使用时,它不是线程安全的。

于 2014-11-12T01:07:51.210 回答
5

我继续使用multiprocessing.dummy.PoolPython 3.4 进行了粗略的实验。实验使用线程池将函数映射到 range(100) 输入,如果函数的输入正好是 10,它会修补一个内部函数以调用 time.sleep()。如果补丁是线程安全的,那么结果都会立即显示,除了 10 的结果会延迟显示;如果它不是线程安全的,那么一些结果会立即出现,而许多其他结果会迟到。

结果表明unittest.mock.patch 确实会改变全局状态。很高兴知道!

于 2014-11-12T00:50:19.953 回答