繁体   English   中英

Python - 多处理意外结果

[英]Python - multiprocessing unexpected results

我有一些包含迭代器的代码,效果很好:

import multiprocessing

m = [0,1,2,3]


class gener(object):
    def __init__(self, m):
        self.m = m
        self.c = 0

    def __iter__(self):
        return self

    def next(self):
        time.sleep(1)
        ret = self.m[self.c]
        self.c += 1
        return ret 


tt  = gener(m)

def gen(t):
    return t.next() 

print gen(tt)
print gen(tt)
print gen(tt)

OUT:

 0 1 2 

但是如果我尝试将其插入到并行进程中,我就不会得到预期的结果:

import time
import multiprocessing

m = [0,1,2,3]


class gener(object):
    def __init__(self, m):
        self.m = m
        self.c = 0

    def __iter__(self):
        return self

    def next(self):
        time.sleep(1)
        ret = self.m[self.c]
        self.c += 1
        return ret 


tt  = gener(m)

def gen(t):
    return t.next() 

job1 = multiprocessing.Process(target=gen, args=(tt,))
print job1.start()

job2 = multiprocessing.Process(target=gen, args=(tt,))
print job2.start()

job3 = multiprocessing.Process(target=gen, args=(tt,))
print job3.start()

OUT:

 <None)> <None)> <None)> 

我无法弄清楚,我怎么能通过并行使用这个迭代器。 有谁能够帮我? 谢谢!

更新:

关注@Anand S Kumar非常有用的帮助,我更新了我的代码,它工作正常,除了输出是模糊的,目前我正在试图弄清楚什么是错的,也许它将成为另一个主题的主题,也许是Anand会帮助我:)):

from threading import Thread, Lock
import time



m = [0,1,2,3]
starter = 0

class gener(object):
    def __init__(self, m):
        self.m = m
        self.c = 0

    def __iter__(self):
        return self

    def next(self):
        time.sleep(1)
        ret = self.m[self.c]
        self.c += 1
        return ret

tt = gener(m)


def f(t):
    global starter
    lock = Lock()
    lock.acquire()
    try:
        starter = t.next()
    finally:
        lock.release() 


t1 = Thread(target=f,args=(tt,))
t1.start()

t2 = Thread(target=f,args=(tt,))
t2.start()

t3 = Thread(target=f,args=(tt,))
t3.start()

t1.join()
print starter
t2.join()
print starter
t3.join()
print starter

不同的输出,使用相同的代码:

 0 1 2 2 2 2 0 2 2 

您正在尝试打印job.start()函数的返回值,该函数不返回任何内容,因此它将打印None

您可以将print语句移动到gen(t)函数中,而不是打印job.start()的返回值,例如 -

def gen(t):
    print t.next()

然后运行该程序,而不打印job.start()

如果要从函数中接收返回值,可以使用多处理模块中的Pool [文档]

文档中的一个例子 -

from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    pool = Pool(processes=4)              # start 4 worker processes
    result = pool.apply_async(f, [10])    # evaluate "f(10)" asynchronously
    print result.get(timeout=1)           # prints "100" unless your computer is *very* slow
    print pool.map(f, range(10))

但请注意,您实际上是在创建多个进程,而不是线程,它们不会共享全局变量。

我相信你想要的是threads ,也许下面的例子可以帮助你开始 -

from threading import Thread, Lock
m = [0,1,2,3]
starter = 0

class gener(object):
    def __init__(self, m):
        self.m = m
        self.c = 0

    def __iter__(self):
        return self

    def next(self):
        ret = self.m[self.c]
        self.c += 1
        return ret 

tt  = gener(m)


def f(t):
    global starter
    lock = Lock()
    lock.acquire()
    try:
        starter = t.next()
    finally:
        lock.release()

t1 = Thread(target=f,args=(tt,))
t1.start()
t2 = Thread(target=f,args=(tt,))
t2.start()
t1.join()
t2.join()

两个问题:

1) start()函数不返回值,因此您将打印出None

2)您将生成器对象传递给每个进程,从而原始的gener对象(在主进程中声明) 复制三次,一次复制到每个forked进程的堆栈。 因此,即使您将功能更改为:

def gen(t):
    print t.next()

所有你要做的就是在每个单独的gener对象上第一次也是唯一一次调用next() ,打印:

0
0
0

为了获得所需的效果,您需要在主进程中执行迭代,并将其结果传递给每个生成的进程:

job1 = multiprocessing.Process(target=gen, args=(tt.next(),))
#print job1.start()

job2 = multiprocessing.Process(target=gen, args=(tt.next(),))
#print job2.start()

job3 = multiprocessing.Process(target=gen, args=(tt.next(),))
#print job3.start()

那么你所有的gen函数需要做的就是print值:

def gen(t):
    print t

你得到:

0
1
2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM