Python多处理池中的奇怪行为

时间:2017-01-29 09:54:29

标签: python python-3.x multiprocessing

Python多处理池在Linux和Windows之间具有不同的行为。

当按照工作人员数量运行方法映射时,在Linux中它会在您给出的特定函数作为参数的范围内运行该过程, 但在Windows中,每个工作程序都在父进程的范围内运行,并再次使用它不应该的代码。

例如:(该烧瓶只是为了使它与我的代码相似)

from multiprocessing import Pool, Event
from flask import Flask

print(">>> This code running for every each worker")

app = Flask(__name__)

terminating = None


def f(**kwargs):
    print("f()")
    x = kwargs.pop("x", 1)
    print(x * x)
    return x * x


def worker_warpper(arg):
    func, kwargs = arg
    return func(**kwargs)


def initializer(terminating_):
    global terminating
    terminating = terminating_


@app.route('/check', methods=['GET'])
def check():
    with Pool(processes=3) as pool:
        ls = [(f, {"x": 2}), (f, {"x": 5}), (f, {"x": 6})]
        pool_map = pool.map(worker_warpper, ls)
    return "Finished"


if __name__ == "__main__":
    print("Listening...")
    app.run(port=5151, host='0.0.0.0')

这段代码应该运行函数" f" (只有函数" f")并行3个不同进程3次。

但它再次在顶部运行打印。 (它并不完全适用于每一个过程 - 但是运行的次数与#34; f"以及顶部的打印数量之间存在关系以再次运行)

print(">>> This code running for every each worker")

仅适用于Windows,仅适用于Linux" f"又跑了。

输出:(Linux)

>>> This code running for new worker (not all of the workers)
Listening
...
 * Running on http://0.0.0.0:5151/ (Press CTRL+C to quit)
f()
4
f()
25
f()
36
127.0.0.1 - - 

[29/Jan/2017 11:46:26] "GET /check HTTP/1.1" 200 -

输出:(Windows)

>>> This code running for new worker (not all of the workers)
Listening
...
 * Running on http://0.0.0.0:5151/ (Press CTRL+C to quit)
>>> This code running for new worker (not all of the workers)
f()
4
f()
25
f()
36
127.0.0.1 - - 

[29/Jan/2017 11:46:26] "GET /check HTTP/1.1" 200 -

为什么linux和windows之间存在不同的行为? 我能做些什么呢?

如果不清楚告诉我,我会以不同的方式尝试。

谢谢!

1 个答案:

答案 0 :(得分:2)

Windows和Linux之间的区别在于子进程的启动方式。在Linux上,使用fork()启动子进程:新进程以与父进程相同的状态启动:python代码已经被解释,并且它获得了父进程内存的副本。

在Windows上它完全不同:进程是spawn ed:启动一个新的python解释器,它再次解析python文件并执行它。这就是为什么再次执行顶部的print进程的原因。

有关详细信息,请参阅the docs about fork vs. spawn

常见的陷阱是避免底部的if __name__ == '__main__'。但是因为你已经在代码中使用了这个,所以你非常接近“安全代码”。

  

我该怎么办?

您可以使用Threading代替多处理。当您启动一个新线程时,新线程使用与父线程相同的内存空间。缺点是,由于蟒蛇“全球解释器锁定”,你只能使用一个CPU核心。

有关详细信息,请参阅this discussion