[英]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.