【问题标题】:Child process not inheriting Python global variable on Windows子进程未在 Windows 上继承 Python 全局变量
【发布时间】:2020-06-12 02:59:21
【问题描述】:

我知道子进程在 fork/spawn 之后不会看到所做的更改,并且 Windows 进程不会继承不使用共享内存的全局变量。但是我遇到的情况是,孩子们看不到在 fork/spawn 之前对共享内存中的全局变量所做的更改。

简单演示:

from multiprocessing import Process, Value
global foo
foo = Value('i',1)
def printfoo():
  global foo 
  with foo.get_lock():
    print(foo.value)
if __name__ == '__main__':
  with foo.get_lock():
    foo.value = 2
  Process(target=printfoo).start()

在 Linux 和 MacOS 上,这显示预期的 2。在 Windows 上,它显示 1,即使在调用 Process 之前对全局值进行了修改。如何使更改也对 Windows 上的子进程可见?

【问题讨论】:

  • @brokenfoot:这不是一个很好的链接。提问者知道多处理在 Windows 和 Linux 上的行为不同,并且他们明确使用了可用于在进程之间共享数据的机制。他们只是使用了错误的机制。
  • 如果我使用了错误的机制,@user2357112supportsMonica,你能告诉我如何正确使用它们吗?我尝试通过调用其 get_lock 方法来包装 Value 访问,但这并没有改变结果。
  • 您的新编辑导致了一个完全不同的问题——您正试图获得一个尚不存在的对象的锁定。这只会在你创建工作进程之前抛出一个 NameError。

标签: python windows global python-multiprocessing


【解决方案1】:

这里的问题是您的子进程创建了一个 共享值,而不是使用父进程创建的那个。您的父进程需要将Value 显式发送给子进程,例如,作为目标函数的参数:

from multiprocessing import Process, Value

def use_shared_value(val):
    val.value = 2

if __name__ == '__main__':
    val = Value('i', 1)
    p = Process(target=use_shared_value, args=(val,))
    p.start()
    p.join()
    print(val.value)

(不幸的是,我没有安装 Windows Python 来测试它。)


子进程不能在 Windows 上继承全局变量,无论这些全局变量是否初始化为 multiprocessing.Value 实例。 multiprocessing.Value 不会改变子进程重新执行你的文件的事实,并且重新执行Value 构造不会使用父进程分配的共享资源。

【讨论】:

  • 是的,我知道我可以将值作为参数传递给孩子,但我希望避免这种情况,因为这是一个破坏性的内部 API 更改。不过,看起来我无法避免它。即使我确实使用了共享值,我仍然需要一个单独的 Lock 并且最终会将 that 作为新参数传递,因此无论哪种方式都是相同的更改。此外,孩子永远不会为了父母的利益而修改价值,所以它根本不必是价值;这就是为什么它最初只是一个常规全局变量,子进程在 POSIX 操作系统上继承它——但在 Windows 上没有。
猜你喜欢
  • 1970-01-01
  • 2012-08-25
  • 2016-03-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
相关资源
最近更新 更多