python支持多線程多進程編程,標准庫模塊threading使得python的多線程編程變得容易,支持很多功能,在python2.6后,python新添加了多進程的標准庫模塊multiprocessing,功能非常類似threading。
下面介紹multiprocessing模塊的一些常用類和方法。
1、multiprocessing.Process
該類原型如下:
class multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={})
group參數通常為None,僅僅是為兼容threading.Thread。
target為可調用對象,被run()函數調用,一般用法就是將函數傳給該參數,交給子進程運行。
name為進程名,如不指定,默認為Process-1,Process-2....這樣的名字,數字隨自己查數量依次遞增。
args為target調用的參數元祖。
kwargs為target調用的關鍵字參數字典。
Process類生成一個process對象,並運行在一個新的單獨的進程內。
一個簡單的使用例子:
1 from multiprocessing import Process 2 import time 3 4 def timetask(times): 5 time.sleep(times) 6 print time.localtime() 7 8 if __name__ == '__main__': 9 arg = 5 10 p = Process(target = timetask, args = (arg,)) 11 p.start() 12 p.join()
每個process對象最多只能調用一次start()方法,join([timeout])方法會阻塞調用process對象的進程,直到timeout時間超時,或者process進程退出。如果timeout設置為None,則無超時時間。對於linux操作系統的進程管理,父進程會等待子進程退出,並收回子進程的資源,然后父進程再退出。如果父進程先於子進程退出,則子進程會被init進程接管。如果父進程沒有退出也沒有回收子進程資源,則子進程會一直停留在僵死狀態。這里join方法就是阻塞父進程,等待子進程執行完畢。
如果在子進程里面要接受標准輸入(如調用raw_input函數),這時候會有問題。因為標准輸入是被父進程占用,因此這里子進程無法從標准輸入讀取數據。
一個解決辦法是將標准輸入描述符,傳入子進程函數:
1 from multiprocessing import Process 2 import sys, os 3 import time 4 5 def intask(x, fileno): 6 sys.stdin = os.fdopen(fileno) 7 while True: 8 in_char = raw_input("Enter to continue, Q to quit: ") 9 if in_char.upper() == 'Q': 10 break 11 print x * x 12 13 if __name__ == '__main__': 14 fn = sys.stdin.fileno() 15 arg = 5 16 p = Process(target = intask, args = (arg, fn)) 17 p.start() 18 p.join()
開啟多個進程並行執行:
1 from multiprocessing import Process 2 import sys, os 3 import time 4 5 def timetask(times): 6 time.sleep(times) 7 print time.localtime() 8 9 10 def works(func, arg, worknum): 11 proc_record = [] 12 for i in range(worknum): 13 p = Process(target = func, args = (arg,)) 14 p.start() 15 proc_record.append(p) 16 for p in proc_record: 17 p.join() 18 19 20 if __name__ == '__main__': 21 arg = 5 22 procs = 4 23 works(timetask, arg, procs)
程序同時開啟4個進程並行執行timetask函數,這里需要注意的是先把所有的進程對象執行了start()方法后,再執行join(),如果對每個進程對象一起執行start()和join(),那么單個進程對象start()后,會馬上阻塞父進程,導致無法馬上對下一個進程對象執行start()。結果就是子進程並不是並行運行,而是依次運行。
有時間再更新multiprocessing模塊的其他類和方法