首页 > 解决方案 > 为什么 multiprocessing.Process 在这里不起作用?

问题描述

我正在 jupyter notebook 和 spyder 上测试多处理:

import multiprocessing
import time

start = time.perf_counter()

def do_something():
    print(f'Sleeping 5 second(s)...')
    time.sleep(5)
    print(f'Done Sleeping...') 


p2 = multiprocessing.Process(target = do_something)
p3 = multiprocessing.Process(target = do_something)

p2.start()
p3.start()

p2.join()
p3.join()

finish = time.perf_counter()

print(f'Finished in {round(finish-start, 2)} secounds')

我得到了:

Finished in 0.12 secounds

这比 5 秒短得多。我确实测试了 do_something 函数,它看起来不错。我觉得在上面的代码中,do_someting 函数甚至没有执行......

start = time.perf_counter()

def do_something(seconds):
    print(f'Sleeping {seconds} second(s)...')
    time.sleep(seconds)
    print(f'Done Sleeping...{seconds}') 

do_something(5)

finish = time.perf_counter()

print(f'Finished in {round(finish-start, 2)} secounds')


Sleeping 5 second(s)...
Done Sleeping...5
Finished in 5.0 secounds

标签: pythonmultiprocessing

解决方案


你的代码应该抛出一个错误(我不会写回溯来保持答案简短):

RuntimeError: 
    An attempt has been made to start a new process before the
    current process has finished its bootstrapping phase.

    This probably means that you are not using fork to start your
    child processes and you have forgotten to use the proper idiom
    in the main module:

        if __name__ == '__main__':
            freeze_support()
            ...

    The "freeze_support()" line can be omitted if the program
    is not going to be frozen to produce an executable.

长话短说:多处理包无法正确理解和执行您的代码。您应该将定义保留在文件的开头,并将要执行的代码放在

if __name__ == '__main__':

否则,每个新进程都将尝试执行相同的文件(并产生其他进程)。在我的电脑上完成更正的代码大约需要 5.22 秒。

在 multiprocessing 包的编程指南(“安全导入主模块”部分)中解释了“if”的需要。请务必阅读它们以避免不必要的行为:多线程和多处理在不正确使用时容易出现难以捉摸的错误。

这是更正后的代码:

import multiprocessing
import time

def do_something():
    print('Sleeping 5 seconds...')
    time.sleep(5)
    print('Done Sleeping.') 

if __name__ == '__main__':
    start = time.perf_counter()

    p2 = multiprocessing.Process(target=do_something, args=())
    p3 = multiprocessing.Process(target=do_something, args=())

    p2.start()
    p3.start()

    p2.join()
    p3.join()

    finish = time.perf_counter()

    print(f'Finished in {round(finish-start, 2)} seconds')

为什么你会在 0.12 秒后看到输出?发生这种情况是因为每个子进程都会抛出错误并崩溃(您应该得到两个相同的运行时错误),然后父进程才能完成。


推荐阅读