python multiprocess发生了一些奇怪的事情

时间:2016-07-13 05:10:21

标签: python

我刚刚测试了python多处理来读取文件或全局变量,但是发生了一些奇怪的事情。

表示例:

import multiprocessing

a = 0

def test(lock, name):    
    global a
    with lock:        
        for i in range(10):
            a = a + 1
        print "in process %d : %d" % (name, a)

def main():    
    lock = multiprocessing.Lock()            

    p1 = multiprocessing.Process(target=test, args=(lock, 1))
    p2 = multiprocessing.Process(target=test, args=(lock, 2))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    print "in main process : %d" % a

if __name__=='__main__':
    main()   

程序读取全局变量,但输出为:

in process 1 : 10
in process 2 : 10
in main process : 0

似乎子流程无法正确获取和编辑全局变量。此外,如果我更改程序以读取文件,则每个子进程将完全读取文件,忽略锁定。

那么这些怎么发生?以及如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

全局变量不在进程之间共享。当您创建并启动一个新的Process()时,该进程将在一个单独的"克隆"内部运行。当前Python解释器的副本。从Process()内更新变量只会将变量本地更新为更新的特定进程。

要在Python流程之间共享数据,我们需要multiprocessing.Pipe()multiprocessing.Queue()multiprocessing.Value()multiprocessing.Array()或其他多处理安全容器。< / p>

以下是基于您的代码的示例:

import multiprocessing

def worker(lock, counter, name):
    with lock:        
        for i in range(10):
            counter.value += 1

        print "In process {}: {}".format(name, counter.value)

def main():
    lock = multiprocessing.Lock()    
    counter = multiprocessing.Value('i', 0)         

    p1 = multiprocessing.Process(target=worker, args=(lock, counter, 1))
    p2 = multiprocessing.Process(target=worker, args=(lock, counter, 2))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    print "In main process: {}".format(counter.value)

if __name__=='__main__':
    main()   

这给了我:

In process 1: 10
In process 2: 20
In main process: 20

现在,如果你真的想要使用全局变量,你可以使用multiprocessing.Manager(),但我认为第一种方法更可取,这是一个更重的&#34;解。这是一个例子:

import multiprocessing

manager = multiprocessing.Manager()
counter = manager.Value('i', 0);

def worker(lock, name):
    global counter

    with lock:        
        for i in range(10):
            counter.value += 1

        print "In process {}: {}".format(name, counter.value)

def main():
    global counter

    lock = multiprocessing.Lock()       

    p1 = multiprocessing.Process(target=worker, args=(lock, 1))
    p2 = multiprocessing.Process(target=worker, args=(lock, 2))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    print "In main process: {}".format(counter.value)

if __name__=='__main__':
    main()