在Python中使用多进程时修改全局变量

6

我最终想做的事情是读取一行文本,对其中的信息进行一些计算,然后将结果添加到全局对象中,但似乎无法实现。例如,在下面的代码中,test始终为0。我知道这是错误的,我尝试过其他方式,但仍然没有成功。

import multiprocessing as mp

File = 'HGDP_FinalReport_Forward.txt'
#short_file = open(File)
test = 0

def pro(temp_line):
    global test
    temp_line = temp_line.strip().split()
    test = test + 1
    return len(temp_line)

if __name__ == "__main__":
    with open("HGDP_FinalReport_Forward.txt") as lines:
        pool = mp.Pool(processes = 10)
        t = pool.map(pro,lines.readlines())

2
全局变量通常是你正在做某些错误的迹象。我建议改变程序的工作方式来避免它们 - 这将在长期内节省你的头痛,而且总有更好的方法。 - Gareth Latty
多进程模块的重点在于它会生成子进程而不是同一进程中的线程,具有所有通常的权衡。不幸的是,文档根本没有解释这些权衡,假设你已经知道它们。如果您遵循文档中的“编程指南”,则可能可以摆脱不理解,但您真的应该学习一下。 - abarnert
2个回答

17

由池生成的工作进程会得到全局变量的副本并对其进行更新。除非您明确设置,否则它们不会共享内存。最简单的解决方案是将test的最终值通过返回值传回主进程。例如(未经测试):

def pro(temp_line):
    test = 0
    temp_line = temp_line.strip().split()
    test = test + 1
    return test, len(temp_line)

if __name__ == "__main__":
    with open("somefile.txt") as lines:
        pool = mp.Pool(processes = 10)
        tests_and_t = pool.map(pro,lines.readlines())
        tests, t = zip(*test_and_t)
        test = sum(tests)

8
重要的是,使用“multiprocessing”,线程(或进程)不共享状态。 - Gareth Latty
2
+1 给答案,以及 +1 @Lattyware。我希望多进程文档能够更清晰地说明“使用类似于线程模块的API生成进程”的区别与“创建线程”,因为这将解决SO上该模块一半的问题... - abarnert
太棒了!它帮助我更新了django模型。显然,连接没有被分叉,可能会被另一个进程不正确地关闭。为了解决这个问题,我使用了这种方法,但我没有使用zip,而是直接使用for循环从列表中访问元组元素,然后对于每个列表项,使用tuple_element[index]遍历元组。 - radtek

0

这里是在多进程中使用全局变量的示例。

我们可以清楚地看到每个进程都使用自己的变量副本:

import multiprocessing
import time
import os
import sys
import random
def worker(a):
    oldValue = get()
    set(random.randint(0, 100))
    sys.stderr.write(' '.join([str(os.getpid()), str(a), 'old:', str(oldValue), 'new:', str(get()), '\n']))

def get():
    global globalVariable
    return globalVariable

globalVariable = -1
def set(v):
    global globalVariable
    globalVariable = v

print get()
set(-2)
print get()

processPool = multiprocessing.Pool(5)
results = processPool.map(worker, range(15))

输出:

27094 0 old: -2 new: 2 
27094 1 old: 2 new: 95 
27094 2 old: 95 new: 20 
27094 3 old: 20 new: 54 
27098 4 old: -2 new: 80 
27098 6 old: 80 new: 62 
27095 5 old: -2 new: 100 
27094 7 old: 54 new: 23 
27098 8 old: 62 new: 67 
27098 10 old: 67 new: 22 
27098 11 old: 22 new: 85 
27095 9 old: 100 new: 32 
27094 12 old: 23 new: 65 
27098 13 old: 85 new: 60 
27095 14 old: 32 new: 71

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