python並發編程-多線程同步異步處理


在學習python多進程時,進程上運行的方法接收多個參數和多個結果時遇到了問題,現在經過學習在這里總結一下

Pool.map()多參數任務
在給map方法傳入帶多個參數的方法不能達到預期的效果,像下面這樣

def job(x ,y):
	return x * y

if __name__ == "__main__":
	pool = multiprocessing.Pool()
	res = pool.map(job, 2, 3)
	print res

所以只能通過對有多個參數的方法進行封裝,在進程中運行封裝后的方法如下

def job(x ,y):
	return x * y


def job1(z):
    return job(z[0], z[1])


if __name__ == "__main__":
	pool = multiprocessing.Pool()
	res = pool.map(job1, [(2, 3), (3, 4)])
	print res

這樣就能達到傳遞多個參數的效果
ps:如果需要得到多個結果可以傳入多個元組在一個列表中

Pool.apply_async()輸出多個迭代結果
在使用apply_async()方法接收多個參數的方法時,在任務方法中正常定義多個參數,參數以元組形式傳入即可
但是給apply_async()方法傳入多個值獲取多個迭代結果時就會報錯,因為該方法只能接收一個值,所以可以將該方法放入一個列表生成式中,如下

def job(x):
    return x * x


if __name__ == "__main__":
    pool multiprocessing.Pool()
    res = [pool.apply_async(target=job, (i,)) for i in range(3)]
    print [r.get() for r in res]

當想要提高一個任務的執行效率時,我們可以通過拆分任務,把這個任務拆分成多個子任務,然后利用多進程進行異步執行,即同時處理,縮短整體的任務時間。在python的multiprocessing包中,有兩個可以構造異步執行的進程任務方法,apply_async()和map_async(),兩者都可以分別添加任務,然后多進程同時執行。但是兩者有着重要區別,下面進行說明。

對於apply_async(func,args),func為要執行任務的函數名,args為一個列表或元組這樣的可迭代對象,里面包含的是要傳遞給func的參數,對於多個子任務,要分別多次調用apply_async()一一添加,不過這可以通過列表解析實現,以讓多個進程的結果返回保存在一個列表中。而對於map_async(func,iterable,chunksize),如果多個子任務通過同一函數執行,只是參數不同,那么可以把拆分后的參數以列表形式通過iterable傳入,並通過chunksize參數指定進程數(實際上這里的chunksize表示的是對iterable的拆分數,但最好讓其等於進程數),這樣就不需要一一添加。

以上只是兩者細微的差別,更重要的差別在於,若是通過apply_async()方法,由於是手動指定進程並添加任務,這樣每個進程的執行結果之間是獨立的,會分別保存,這樣的好處在於,盡管可能其中某幾個進程出現了錯誤,拋出異常,但是並不會導致其他的進程也失敗,其他的進程並不會受影響,而且當獲取這個拋出異常的進程的結果時,還會返回異常信息;但是如果是map_async()方法,其子參數任務並不是獨立的,如果其中的某個子參數任務拋出異常,同時也會導致其他的子參數任務停止,也就是說,並不是通過獨立線程來執行不同的子參數任務的。

通過上述的對比,可知當拆分任務一提高執行效率時,通過列表解析使用apply_async()方法添加子任務,使用獨立多進程去執行是比map_async()方法更好的,因此這種情況下,apply_async()是最優選擇。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM