在編寫Python程序時,經常需要同時執行多個運算任務或多項工作以實現某些功能和使用計算機的多核提高執行效率,這裏介紹一種非常簡單的方法實現多進程。
使用multiprocessing.Pool
實現進程池
這裏使用的是multiprocessing
提供的Pool
方法來實現多進程
以下述代碼爲例:
from multiprocessing import Pool # 導入線程池
import os, time, random # 導入其他包
def long_time_task(name): # 子進程的任務
print('Run task %s (%s)...' % (name, os.getpid())) # os.getpid()爲獲取進程號
start = time.time() # 開始計時
time.sleep(random.random() * 10) # 等待一段時間,模擬計算耗費時間
end = time.time() # 等待完成時間戳
print('Task %s runs %0.2f seconds.' % (name, (end - start))) # 任務執行完成,輸出任務執行時間
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4) # 創建進程池
for i in range(10):
p.apply_async(long_time_task, args=(i,)) # 向進程池中添加任務
print('Waiting for all subprocesses done...')
p.close() # 結束向進程池中添加任務(後續不能再使用apply_async方法添加新任務)
p.join() # 實現進程同步
print('All subprocesses done.')
這段代碼中的long_time_task
方法是需要同時進行執行的方法。
在主函數中,首先通過p = Pool(4)
創建進程池,數字代表同時執行的子進程數量,若留空,默認爲系統安裝的核心數
隨後,使用p.apply_async()
方法向進程池中添加任務。其中long_time_task
是將要執行的函數,而args
則指代的是函數需要傳入的變量,需要注意這裏要以元組
的形式傳入。
若添加的任務數超出了設定的允許同時執行的最大任務數,則後續進程排隊,待正在執行的子進程結束後進入執行(可以參考銀行的多櫃檯排隊,進程池設定的同時執行的子進程數量相當於銀行的辦理窗口,添加的進程相當於前往銀行辦理業務的客戶,當客戶數量超過了開放的窗口數,後續用戶開始排隊)
隨後,使用p.close()
作爲所有子任務添加完成的信號,在使用p.join()
命令前必須運行該命令
最後,使用p.join()
實現子進程和母進程的同步。也就是主進程執行到此處後進行確認,確認所有子進程是否已經進行完成。如果所有子進程都已經執行完成,則繼續執行後續代碼;若子進程仍然在進行中,則在此處等待,直到所有子進程全部執行完成再執行後續代碼。(繼續援引前面的例子,可以理解爲銀行關門前,需要等待所有客戶處理完業務)
使用multiprocessing.Process
實現簡單多進程
此方法適合只需要添加一兩個子進程的情況下使用,實現更爲簡便
from multiprocessing import Process # 導入多進程所需包
import os
import time
def run_proc(name):
print('Run child process %s (%s)...' % (name, os.getpid()))
print('child process wait 10s')
time.sleep(10) # 子進程執行任務
print('child process finished waiting')
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',)) # 添加子進程
print('Child process will start.')
p.start() # 子進程開始執行
print('parent process sleep 5s')
time.sleep(5) # 母進程執行其他任務
print('parnet process finished sleeping')
p.join() # 實現母進程與子進程的同步,確認子進程執行完後繼續後續操作
print('Child process end.')
此方法與上述進程池的實現非常類似,這裏不再贅述。
此外在Linux \ Unix
系統下,還可以通過os.fork()
方法實現子進程,但是由於Windows下無法使用
,且略微繁瑣,故在此不述。