Python 多进程 - 全局列表中的共享计数器未正确递增
我正在尝试在多进程中实现一个共享计数器。我使用一个全局变量来避免序列化的问题。但我不明白的是,增加计数的操作似乎没有作用在我的全局计数器列表上(值总是0)。我猜代码可能在使用一个局部变量的实例,而这个实例最后被丢弃了。
我以为全局列表是可以修改的,因为它们是可变的。我还尝试明确地定义 global list_global
来说明我想使用这个变量的全局定义。
有人能指出我哪里出错了吗?
from multiprocessing import Pool, Value, Lock
list_global = [] # global variable to hold Counter values
#http://eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessing/
class Counter(object):
def __init__(self, initval=0):
self.val = Value('i', initval)
self.lock = Lock()
## self.val = initval
def increment(self):
with self.lock:
self.val.value += 1
def value(self):
with self.lock:
return self.val.value
def process_item(x):
global list_global
list_global[0].increment() # increments
return list_global[0].value() # correctly returns incremented value
def main():
global list_global
print 'before', list_global[0].value()
pool = Pool()
print pool.map(process_item, range(10))
pool.close()
pool.join()
#increments in process_item are not persistent
#(do not appear to be modifying the global variable)
print 'after', list_global[0].value() #=> 0
# list_global holds 3 Counter objects
for i in range(3):
list_global.append(Counter(0))
if __name__ == '__main__':
global list_global
main()
#print list_global # list_global holds "Counter" objects
for i in list_global:
print i.value(), #=>[0,0,0] # expected [10,0,0]
1 个回答
2
更具体地说,你的问题在于你对多进程的理解有误,这导致你对输出结果的期望不正确。你不能声明一个全局变量然后在多个进程之间共享它。使用线程时情况会稍微好一些,但要理解你遇到的问题,首先需要明白多进程到底在做什么。
当 Pool.map()
启动你的子进程时,每个子进程都会启动一个 自己的 Python 解释器,并在其中导入你的顶层函数 process_item
。这个独立的解释器实例也会创建 它自己的 list_global
实例。这个过程会在 每个 子进程中发生。你对 global
的调用并不会神奇地让这些独立运行的进程共享你模块中定义的列表。