通過實例解析python創(chuàng)建進程常用方法
運行程序時,單線程或單進程往往是比較慢的,為加快程序運行速度,我們可以使用多進程,可以理解為多任務同時運行,小編的電腦是四核,所以可以設置四個進程。
下面,我們來了解下多進程的使用:
1、使用multiprocessing模塊創(chuàng)建進程
multiprocessing模塊提供了一個Process類來代表進程對象,語法如下:
Process([group[,target[,name[,args[,kwargs]]]]])
其中,group:參數(shù)未使用,值始終是None
target:表示當前進程啟動時執(zhí)行的可調用對象
name:為當前進程實例的別名
args:表示傳遞給target函數(shù)的參數(shù)元組
kwargs:表示傳遞給target函數(shù)的參數(shù)字典
使用多進程的一個簡單例子:
from multiprocessing import Process # 導入模塊
# 執(zhí)行子進程代碼
def test(interval):
print('我是子進程')
# 執(zhí)行主程序
def main():
print('主進程開始')
# 實例化Procss進程類
p = Process(target=test,args=(1,))
# 啟動子進程
p.start()
print('主進程結束')
if __name__ == '__main__':
main()
結果:
主進程開始
主進程結束
我是子進程
Process的實例p常用的方法除start()外,還有如下常用方法:
is_alive():判斷進程實例是否還在執(zhí)行
join([timeout]):是否等待進程實例執(zhí)行結束,或等待多少秒
start():啟動進程實例(創(chuàng)建子進程)
run():如果沒有給定target參數(shù),對這個對象調用start()方法時,就將執(zhí)行對象中的run()方法
terminate():不管任務是否完成,立即終止
Process類還有如下常用屬性:
name:當前進程實例別名,默認為Process-N,N為從1開始遞增的整數(shù)
pid:當前進程實例的PID值
下面是Process類方法和屬性的使用,創(chuàng)建兩個子進程,分別使用os模塊和time模塊輸出父進程和子進程的id以及子進程的時間,并調用Process類的name和pid屬性:
# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os
#兩個子進程將會調用的兩個方法
def child_1(interval):
print("子進程(%s)開始執(zhí)行,父進程為(%s)" % (os.getpid(), os.getppid()))
# 計時開始
t_start = time.time()
# 程序將會被掛起interval秒
time.sleep(interval)
# 計時結束
t_end = time.time()
print("子進程(%s)執(zhí)行時間為'%0.2f'秒"%(os.getpid(),t_end - t_start))
def child_2(interval):
print("子進程(%s)開始執(zhí)行,父進程為(%s)" % (os.getpid(), os.getppid()))
# 計時開始
t_start = time.time()
# 程序將會被掛起interval秒
time.sleep(interval)
# 計時結束
t_end = time.time()
print("子進程(%s)執(zhí)行時間為'%0.2f'秒"%(os.getpid(),t_end - t_start))
if __name__ == '__main__':
print("------父進程開始執(zhí)行-------")
# 輸出當前程序的ID
print("父進程PID:%s" % os.getpid())
# 實例化進程p1
p1=Process(target=child_1,args=(1,))
# 實例化進程p2
p2=Process(target=child_2,name="mrsoft",args=(2,))
# 啟動進程p1
p1.start()
# 啟動進程p2
p2.start()
#同時父進程仍然往下執(zhí)行,如果p2進程還在執(zhí)行,將會返回True
print("p1.is_alive=%s"%p1.is_alive())
print("p2.is_alive=%s"%p2.is_alive())
#輸出p1和p2進程的別名和PID
print("p1.name=%s"%p1.name)
print("p1.pid=%s"%p1.pid)
print("p2.name=%s"%p2.name)
print("p2.pid=%s"%p2.pid)
print("------等待子進程-------")
# 等待p1進程結束
p1.join()
# 等待p2進程結束
p2.join()
print("------父進程執(zhí)行結束-------")
結果:
------父進程開始執(zhí)行------- 父進程PID:13808 p1.is_alive=True p2.is_alive=True p1.name=Process-1 p1.pid=13360 p2.name=mrsoft p2.pid=21500 ------等待子進程------- 子進程(13360)開始執(zhí)行,父進程為(13808) 子進程(21500)開始執(zhí)行,父進程為(13808) 子進程(13360)執(zhí)行時間為'1.01'秒 子進程(21500)執(zhí)行時間為'2.00'秒 ------父進程執(zhí)行結束-------
上述代碼中,第一次實例化Process類時,會為name屬性默認賦值為Process-1,第二次則默認為Process-2,但由于實例化進程p2時,設置了name屬性為mrsoft,所以p2.name的值為mrsoft。
2、使用Process子類創(chuàng)建進程
對于一些簡單的小任務,通常使用Process(target=test)方式實現(xiàn)多進程。但如果要處理復雜任務的進程,通常定義一個類,使其繼承Process類,下面是通過使用Process子類創(chuàng)建多個進程。
# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os
#繼承Process類
class SubProcess(Process):
# 由于Process類本身也有__init__初識化方法,這個子類相當于重寫了父類的這個方法
def __init__(self,interval,name=''):
# 調用Process父類的初始化方法
Process.__init__(self)
# 接收參數(shù)interval
self.interval = interval
# 判斷傳遞的參數(shù)name是否存在
if name:
# 如果傳遞參數(shù)name,則為子進程創(chuàng)建name屬性,否則使用默認屬性
self.name = name
#重寫了Process類的run()方法
def run(self):
print("子進程(%s) 開始執(zhí)行,父進程為(%s)"%(os.getpid(),os.getppid()))
t_start = time.time()
time.sleep(self.interval)
t_stop = time.time()
print("子進程(%s)執(zhí)行結束,耗時%0.2f秒"%(os.getpid(),t_stop-t_start))
if __name__=="__main__":
print("------父進程開始執(zhí)行-------")
# 輸出當前程序的ID
print("父進程PID:%s" % os.getpid())
p1 = SubProcess(interval=1,name='mrsoft')
p2 = SubProcess(interval=2)
#對一個不包含target屬性的Process類執(zhí)行start()方法,就會運行這個類中的run()方法,
#所以這里會執(zhí)行p1.run()
# 啟動進程p1
p1.start()
# 啟動進程p2
p2.start()
# 輸出p1和p2進程的執(zhí)行狀態(tài),如果真正進行,返回True,否則返回False
print("p1.is_alive=%s"%p1.is_alive())
print("p2.is_alive=%s"%p2.is_alive())
#輸出p1和p2進程的別名和PID
print("p1.name=%s"%p1.name)
print("p1.pid=%s"%p1.pid)
print("p2.name=%s"%p2.name)
print("p2.pid=%s"%p2.pid)
print("------等待子進程-------")
# 等待p1進程結束
p1.join()
# 等待p2進程結束
p2.join()
print("------父進程執(zhí)行結束-------")
結果:
------父進程開始執(zhí)行------- 父進程PID:2512 p1.is_alive=True p2.is_alive=True p1.name=mrsoft p1.pid=20328 p2.name=SubProcess-2 p2.pid=13700 ------等待子進程------- 子進程(20328) 開始執(zhí)行,父進程為(2512) 子進程(13700) 開始執(zhí)行,父進程為(2512) 子進程(20328)執(zhí)行結束,耗時1.00秒 子進程(13700)執(zhí)行結束,耗時2.00秒 ------父進程執(zhí)行結束-------
上述代碼中,定義了一個SubProcess子類,繼承multiprocess.Process父類。SubProcess子類中定義了兩個方法:__init__()初始化方法和run()方法,在__init__()初始化方法中,調用父類multiprocess.Process的__init__()初始化方法,否則父類的__init__()方法會被覆蓋,無法開啟進程。此外,在SubProcess子類中沒有定義start()方法,但在主程序中卻調用了start()方法,此時就會自動執(zhí)行SubProcess類的run()方法。
3、使用進程池Pool創(chuàng)建進程
上面我們使用Process類創(chuàng)建了兩個進程,但如果要創(chuàng)建十幾個或者上百個進程,則需要實例化更多的Process類,解決這一問題的方法就是使用multiprocessing模塊提供的pool類,即Pool進程池。
我們先來了解下Pool類的常用方法:
apply_async(func[,args[,kwds]]):使用非阻塞方式調用func()函數(shù)(并行執(zhí)行,阻塞方式必須等待上一個進程退出才能執(zhí)行下一個進程),args為傳遞給func()函數(shù)的參數(shù)列表, kwds為傳遞給func()函數(shù)的關鍵字參數(shù)列表
apply(func[,args[,kwds]]):使用阻塞方式調用func()函數(shù)
close():關閉Pool,使其不再接受新的任務
terminate():不管任務是否完成,立即終止
join():主進程阻塞,等待子進程的退出,必須在close或terminate之后使用
下面通過一個示例演示一下如何通過進程池創(chuàng)建多進程,設置最大進程數(shù)為3,使用非阻塞方式執(zhí)行10個任務:
# -*- coding=utf-8 -*-
from multiprocessing import Pool
import os, time
def task(name):
print('子進程(%s)執(zhí)行task %s ...' % ( os.getpid() ,name))
# 休眠1秒
time.sleep(1)
if __name__=='__main__':
print('父進程(%s).' % os.getpid())
# 定義一個進程池,最大進程數(shù)3
p = Pool(3)
# 從0開始循環(huán)10次
for i in range(10):
# 使用非阻塞方式調用task()函數(shù)
p.apply_async(task, args=(i,))
print('等待所有子進程結束...')
# 關閉進程池,關閉后p不再接收新的請求
p.close()
# 等待子進程結束
p.join()
print('所有子進程結束.')
結果:
父進程(3856). 等待所有子進程結束... 子進程(18872)執(zhí)行task 0 ... 子進程(11220)執(zhí)行task 1 ... 子進程(10140)執(zhí)行task 2 ... 子進程(18872)執(zhí)行task 3 ... 子進程(11220)執(zhí)行task 4 ... 子進程(10140)執(zhí)行task 5 ... 子進程(18872)執(zhí)行task 6 ... 子進程(11220)執(zhí)行task 7 ... 子進程(10140)執(zhí)行task 8 ... 子進程(18872)執(zhí)行task 9 ... 所有子進程結束.
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
python中實現(xiàn)控制小數(shù)點位數(shù)的方法
今天小編就為大家分享一篇python中實現(xiàn)控制小數(shù)點位數(shù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01
pandas將list數(shù)據(jù)拆分成行或列的實現(xiàn)
這篇文章主要介紹了pandas將list數(shù)據(jù)拆分成行或列的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12
selenium+python實現(xiàn)文件上傳操作的方法實例
文件上傳功能是我們在日常開發(fā)中經(jīng)常會遇到的一個需求,下面這篇文章主要給大家介紹了關于selenium+python實現(xiàn)文件上傳操作的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2021-08-08

