在Windows上进行Python多进程处理

5

我是Python编程的新手,需要一些帮助来理解Python解释器的流程,特别是在多进程的情况下。请注意,我正在Windows 10上运行Python 3.7.1。这是我的简单实验代码和输出。

import multiprocessing
import time


def calc_square(numbers, q):
    for n in numbers:
        q.put(n*n)
        time.sleep(0.2)

    q.put(-1)
    print('Exiting function')


print('Now in the main code. Process name is: ' + __name__)

if __name__ == '__main__':
    numbers = [2, 3, 4, 5]
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=calc_square, args=(numbers, q))

    p.start()

    while True:
        if q.empty() is False:
            nq = q.get()
            print('Message is:' + str(nq))
            if nq == -1:
                break
    print('Done')

    p.join()

Program Output:

Now in the main code. Process name is: __main__
Now in the main code. Process name is: __mp_main__
Message is:4
Message is:9
Message is:16
Message is:25
Exiting function
Message is:-1
Done

Process finished with exit code 0

我看过一些代码示例,它们不包含 if name 限定符。我尝试运行其中一个示例,但是出现了多个错误,指向在进程 init 完成之前尝试启动进程。根据该代码的作者所说,在 Linux 上可以工作,因为它使用 fork,而 Windows 不支持(后来我了解到 Windows 使用 spawn 作为进程启动方法)。
我的问题集中在进程似乎执行目标范围之外的指令上。我惊讶地看到输出的第二行在目标发送消息给父进程之前就已经打印出来了。为什么子进程解释器会运行目标范围之外的代码?它真的在运行目标代码之前运行那段代码吗?为什么?

非常感谢您指引我正确的方向。我确实进行了搜索,但显然不够彻底。这对我非常有帮助。 - user10832440
1个回答

11

在Windows上,新进程会导入主要脚本并执行它。因此,在Windows上,您需要if __name__ == '__main__':…它可以防止该if下的代码在每个进程中运行。

您的Now in main code.行在if之外,因此它将在每个进程中运行。将其移至if内部:

import multiprocessing
import time

def calc_square(numbers, q):
    for n in numbers:
        q.put(n*n)
        time.sleep(0.2)

    q.put(-1)
    print('Exiting function')

if __name__ == '__main__':
    print('Now in the main code. Process name is:', __name__)
    numbers = [2, 3, 4, 5]
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=calc_square, args=(numbers, q))
    p.start()

    while True:
        nq = q.get()
        print('Message is:', nq)
        if nq == -1:
            break

    print('Done')
    p.join()

谢谢您的解释。我故意将“在主代码中”的打印放在“if”之外,以确认子进程解释器实际上正在执行代码,并且是在目标被执行之前。我看到由于Python的动态性质,一个新的解释器需要在目标处于正确环境之前执行代码。 - user10832440
如果无法使用__name__子句怎么办?例如,如果我想从类方法中以多进程模式调用函数呢? - Andrea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接