前面我們學(xué)習(xí)了線程,我們也對進(jìn)程做過相關(guān)介紹,學(xué)習(xí)過線程之后,大家能夠知道線程是進(jìn)程的最小單元,這一節(jié)我們就來學(xué)習(xí)一下如何去創(chuàng)建一個進(jìn)程,在Python中給我們提供了多個模塊去創(chuàng)建進(jìn)程,常用的有multiprocessing模塊、os.fork()函數(shù)和Pool進(jìn)程池,這三種方式中,os.fork只能在Linux、mac和UNIX系統(tǒng)使用,不可在windows中使用,而multiprocessing和pool進(jìn)程池都是跨平臺的,本節(jié)我們主要來學(xué)習(xí)一下multiprocessing模塊。
1. multiprocessing模塊
Multiprocessing模塊主要復(fù)制線程模塊的API,為我們提供一個Process類來創(chuàng)建進(jìn)程對象,它的語法格式為:
Process(group=None,target=None,name=None,args=(),kwargs={},daemon=None)
group總是為None,它只與線程兼容 ,target是run()方法要調(diào)用的可調(diào)用對象,默認(rèn)為“無”,即不調(diào)用任何內(nèi)容。name是進(jìn)程名。args是目標(biāo)調(diào)用的參數(shù)元組。kwargs是目標(biāo)調(diào)用的關(guān)鍵字參數(shù)字典,如果提供,關(guān)鍵字only daemon參數(shù)會將進(jìn)程守護(hù)程序標(biāo)志設(shè)置為True或False。如果沒有(默認(rèn)),則此標(biāo)志將從創(chuàng)建過程繼承。
我們通過Process類來創(chuàng)建一個進(jìn)程,代碼如下:
import multiprocessing def process(): print('創(chuàng)建了一個子進(jìn)程') if __name__ == '__main__': print('主進(jìn)程開始') process_one = multiprocessing.Process(target = process,args = ()) process_one.start() print('主進(jìn)程完成')
運行結(jié)果如下:
主進(jìn)程開始 主進(jìn)程完成 創(chuàng)建了一個子進(jìn)程
創(chuàng)建進(jìn)程的方式和創(chuàng)建線程的方式大體一致,創(chuàng)建完成后都是通過start()函數(shù)來使用,除了start(),還有一些方法供我們使用:
1) run()
表示進(jìn)程活動的方法,我們在前面提到線程中也使用了這種方法。
2) join([timeout])
如果可選參數(shù)timeout為None(默認(rèn)值),則方法將阻塞,直到調(diào)用其join()方法的進(jìn)程終止。如果timeout是正數(shù),則它最多阻塞超時秒數(shù)。請注意,如果方法的進(jìn)程終止或方法超時,則該方法將返回None。檢查進(jìn)程的退出代碼以確定它是否終止。
3) is_alive()
返回進(jìn)程是否活動。
4) terminate()
終止進(jìn)程,在Unix上,這是使用SIGTERM信號完成的;在Windows上,使用TerminateProcess(),退出處理程序和最后子句等將不會被執(zhí)行。
5) Close()
關(guān)閉流程對象,釋放與之關(guān)聯(lián)的所有資源。如果基礎(chǔ)進(jìn)程仍在運行,則引發(fā)ValueError。一旦close()成功返回,Process對象的大多數(shù)其他方法和屬性都將引發(fā)ValueError。
6) kill()
和terminate() 類似,但在Unix上使用SIGKILL信號。
7) Pid
返回進(jìn)程ID。
2. 使用Process子類創(chuàng)建進(jìn)程
我們在前面學(xué)習(xí)線程的時候?qū)W習(xí)了使用Thread子類創(chuàng)建線程,進(jìn)程和線程一樣可以通過Process子類中的方法來創(chuàng)建子進(jìn)程,大家可以嘗試模仿著線程的創(chuàng)建方式去創(chuàng)建一個子進(jìn)程。
import multiprocessing import time import datetime import os class MyProcess(multiprocessing.Process): def __init__(self,name = None):#使用父類中的初始化方法 multiprocessing.Process.__init__(self)#接受參數(shù) if name:#判斷傳遞的參數(shù)是否存在 self.name = name def run(self): print('子進(jìn)程開始的時間為:',datetime.datetime.now()) print('子進(jìn)程%s正在執(zhí)行'%os.getpid()) time.sleep(5) print('子進(jìn)程執(zhí)行完畢的結(jié)束時間為', datetime.datetime.now()) if __name__ == '__main__': print('父進(jìn)程PID為',os.getpid()) print('父進(jìn)程開始執(zhí)行的時間為:',datetime.datetime.now()) process_one = MyProcess() process_one.start()#啟動進(jìn)程 process_one.join()#等待進(jìn)程執(zhí)行結(jié)束 print('父進(jìn)程結(jié)束執(zhí)行的時間為:',datetime.datetime.now())
輸出結(jié)果為:
父進(jìn)程PID為 12424 父進(jìn)程開始執(zhí)行的時間為: 2020-02-09 19:52:36.045122 子進(jìn)程開始的時間為: 2020-02-09 19:52:36.145852 子進(jìn)程924正在執(zhí)行 子進(jìn)程執(zhí)行完畢的結(jié)束時間為 2020-02-09 19:52:41.146354 父進(jìn)程結(jié)束執(zhí)行的時間為: 2020-02-09 19:52:41.155225
我們在這個例子中引入了時間模塊,我們可以通過時間來觀察父進(jìn)程和子進(jìn)程的關(guān)系,使用Process子類創(chuàng)建子進(jìn)程的方式基本上和創(chuàng)建線程的一樣,同樣要注意join()的使用,不使用join()方法的時候主線程會提前結(jié)束,這一點我們可以通過注釋掉 process_one.join()去觀察一下。
3. 總結(jié)
學(xué)習(xí)過線程的相關(guān)內(nèi)容之后,進(jìn)程的內(nèi)容就顯得簡單了很多,跟著章節(jié)的順序?qū)W習(xí)能夠提高大家的學(xué)習(xí)效率。
C語言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點擊了解:
一點編程也不會寫的:零基礎(chǔ)C語言學(xué)練課程
解決困擾你多年的C語言疑難雜癥特性的C語言進(jìn)階課程
從零到寫出一個爬蟲的Python編程課程
只會語法寫不出代碼?手把手帶你寫100個編程真題的編程百練課程
信息學(xué)奧賽或C++選手的 必學(xué)C++課程
藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競賽課入門課程
手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程