是否可以在多处理中运行 `mock.patch` 函数(使用 `spawn`)?

Alo*_*nme 9 python macos mocking python-multiprocessing python-3.8

是否可以mock.patch在子进程中运行一个函数,该子进程是使用设置为的multiprocessing模块创建的?start methodspawn

如果没有修补子进程forked的解决方案,那么绕过这个问题的正确解决方案是什么?

重要的是要说改用 fork 并不能解决我的问题。从 python3.8-macOS 开始,多处理启动方法的默认行为是spawn.

multiprocessing文档:

Changed in version 3.8: On macOS, the spawn start method is now the default. The fork start method should be considered unsafe as it can lead to crashes of the subprocess. See bpo-33725..

示例代码(在 python >= 3.8 的 macos 上运行):

import multiprocessing
import unittest
from unittest import mock


def baz(i):
    print(i)


def bar(i):  #  Middle function to avoid a pickeling problem with mocks
    baz(i)


def foo():
    with multiprocessing.Pool(2) as pool:
        pool.map(bar, [i for i in range(10)])


class TestClass(unittest.TestCase):
    @mock.patch(f'{__name__}.baz', return_value=None)
    def test_case(self, mock):
        # multiprocessing.set_start_method('fork', force=True)
        foo()

Run Code Online (Sandbox Code Playgroud)

baz以下输出所示,该函数未在生成的进程中打补丁(因此,它会打印)。更改默认启动方式(代码中注释)解决问题

输出:

============================================================================== test session starts ===============================================================================
platform darwin -- Python 3.8.0, pytest-5.4.3, py-1.8.2, pluggy-0.13.1
rootdir: /Users/alonmenczer/dev/path_test/proj
collected 1 item

mp_spawn.py 0
1
4
5
6
7
8
9
2
3
.

=============================================================================== 1 passed in 0.27s ================================================================================
Run Code Online (Sandbox Code Playgroud)

blu*_*yke -6

是的,这绝对是,只是取决于如何

from multiprocessing import Process
import os

def info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())
    print('process id:', os.getpid())

def f(name):
    info('function f')
    print('hello', name)

if __name__ == '__main__':
    info('main line')
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
Run Code Online (Sandbox Code Playgroud)

  • 您能为答案添加一些解释吗?这如何解决这个问题?添加到多处理模块文档的链接是什么意思? (3认同)