生成过程中的静态变量未初始化

问题描述

对我来说很奇怪,“spawn”过程没有复制类的静态变量,但是使用“fork”一切正常。

代码

import typing as t
import multiprocessing as mp
from concurrent.futures import ProcesspoolExecutor


class Foo:
    static_var: int

    def __init__(self):
        pass


def func(foo_class: t.Type[Foo]):
    return foo_class.static_var


if __name__ == "__main__":
    # with ProcesspoolExecutor(mp_context=mp.get_context("fork")) as executor:
    with ProcesspoolExecutor(mp_context=mp.get_context("spawn")) as executor:
        foo_class = Foo
        foo_class.static_var = 10
        res = executor.map(func,[foo_class,foo_class])
        print(list(res))
    print('Done')

输出“叉”:

[10,10]
Done

输出生成”:

AttributeError: type object 'Foo' has no attribute 'static_var'

Python 版本:3.8.5

我不知道如何用 spawn 克服它(我不完全理解为什么它不起作用)。 Spawn 进程启动自己的解释器并再次导入模块(和类?),这就是未初始化静态变量的原因? 如何通过类传递变量?

解决方法

在多处理中,spwanfork-server 工作进程是新的 Python 进程。
所有内存状态都是新鲜的,FROM node:latest RUN apt-get update \ && apt-get install -y wget gnupg ca-certificates \ && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ && apt-get update \ # We install Chrome to get all the OS level dependencies,but Chrome itself # is not actually used as it's packaged in the node puppeteer library. # Alternatively,we could could include the entire dep list ourselves # (https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix) # but that seems too easy to get out of date. && apt-get install -y google-chrome-stable \ && rm -rf /var/lib/apt/lists/* \ && wget --quiet https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh -O /usr/sbin/wait-for-it.sh \ && chmod +x /usr/sbin/wait-for-it.sh RUN mkdir -p /app/src WORKDIR /app/src # COPY package.json . COPY package.json package-lock.json ./ RUN npm install COPY . . #EXPOSE 4001 CMD ["node","puppeteer-one-page.js"] 块没有被执行。 这个意义上的静态类变量不是静态的。

if __name__ == "__main__:" 工作进程中,整个进程内存被复制,因此类变量很可能被复制,但一个进程中的任何更改都不会影响其他进程。

两种可能的解决方案:

  • 修改任务函数和参数,使任务自包含,不依赖于非静态环境。
  • 使用 fork 中的 initializer 参数正确设置静态变量。
ProcessPoolExecutor