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)