multiprocessing模塊提供了一個Process類來代表一個進(jìn)程對象,下面的例子演示了啟動一個子進(jìn)程并等待其結(jié)束:
#coding=utf-8
from multiprocessing import Process
import os
# 子進(jìn)程要執(zhí)行的代碼
def run_proc(name):
print('子進(jìn)程運行中,name= %s ,pid=%d...' % (name, os.getpid()))
if __name__=='__main__':
print('父進(jìn)程 %d.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('子進(jìn)程將要執(zhí)行')
p.start()
p.join()
print('子進(jìn)程已結(jié)束')
執(zhí)行結(jié)果:
join()方法可以等待子進(jìn)程結(jié)束后再繼續(xù)往下運行,通常用于進(jìn)程間的同步。
<h3>Process語法結(jié)構(gòu)如下:</h3>
Process([group [, target [, name [, args [, kwargs]]]]])
target:表示這個進(jìn)程實例所調(diào)用對象;
args:表示調(diào)用對象的位置參數(shù)元組;
kwargs:表示調(diào)用對象的關(guān)鍵字參數(shù)字典;
name:為當(dāng)前進(jìn)程實例的別名;
group:大多數(shù)情況下用不到;
Process類常用方法:
is_alive():判斷進(jìn)程實例是否還在執(zhí)行;
join([timeout]):是否等待進(jìn)程實例執(zhí)行結(jié)束,或等待多少秒;
start():啟動進(jìn)程實例(創(chuàng)建子進(jìn)程);
run():如果沒有給定target參數(shù),對這個對象調(diào)用start()方法時,就將執(zhí)行對象中的run()方法;
terminate():不管任務(wù)是否完成,立即終止;
Process類常用屬性:
name:當(dāng)前進(jìn)程實例別名,默認(rèn)為Process-N,N為從1開始遞增的整數(shù);
pid:當(dāng)前進(jìn)程實例的PID值;
<h4>實例1</h4>
from multiprocessing import Process
import os
from time import sleep
# 子進(jìn)程要執(zhí)行的代碼
def run_proc(name, age, **kwargs):
for i in range(10):
print('子進(jìn)程運行中,name= %s,age=%d ,pid=%d...' % (name, age,os.getpid()))
print(kwargs)
sleep(0.5)
if __name__=='__main__':
print('父進(jìn)程 %d.' % os.getpid())
p = Process(target=run_proc, args=('test',18), kwargs={"m":20})
print('子進(jìn)程將要執(zhí)行')
p.start()
sleep(1)
p.terminate()
p.join()
print('子進(jìn)程已結(jié)束')
結(jié)果:
父進(jìn)程 21378.
子進(jìn)程將要執(zhí)行
子進(jìn)程運行中,name= test,age=18 ,pid=21379...
{'m': 20}
子進(jìn)程運行中,name= test,age=18 ,pid=21379...
{'m': 20}
子進(jìn)程已結(jié)束
<h4>實例2</h4>
#coding=utf-8
from multiprocessing import Process
import time
import os
#兩個子進(jìn)程將會調(diào)用的兩個方法
def worker_1(interval):
print("worker_1,父進(jìn)程(%s),當(dāng)前進(jìn)程(%s)"%(os.getppid(),os.getpid()))
t_start = time.time()
time.sleep(interval) #程序?qū)粧炱餴nterval秒
t_end = time.time()
print("worker_1,執(zhí)行時間為'%0.2f'秒"%(t_end - t_start))
def worker_2(interval):
print("worker_2,父進(jìn)程(%s),當(dāng)前進(jìn)程(%s)"%(os.getppid(),os.getpid()))
t_start = time.time()
time.sleep(interval)
t_end = time.time()
print("worker_2,執(zhí)行時間為'%0.2f'秒"%(t_end - t_start))
#輸出當(dāng)前程序的ID
print("進(jìn)程ID:%s"%os.getpid())
#創(chuàng)建兩個進(jìn)程對象,target指向這個進(jìn)程對象要執(zhí)行的對象名稱,
#args后面的元組中,是要傳遞給worker_1方法的參數(shù),
#因為worker_1方法就一個interval參數(shù),這里傳遞一個整數(shù)2給它,
#如果不指定name參數(shù),默認(rèn)的進(jìn)程對象名稱為Process-N,N為一個遞增的整數(shù)
p1=Process(target=worker_1,args=(2,))
p2=Process(target=worker_2,name="dongGe",args=(1,))
#使用"進(jìn)程對象名稱.start()"來創(chuàng)建并執(zhí)行一個子進(jìn)程,
#這兩個進(jìn)程對象在start后,就會分別去執(zhí)行worker_1和worker_2方法中的內(nèi)容
p1.start()
p2.start()
#同時父進(jìn)程仍然往下執(zhí)行,如果p2進(jìn)程還在執(zhí)行,將會返回True
print("p2.is_alive=%s"%p2.is_alive())
#輸出p1和p2進(jìn)程的別名和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)
#join括號中不攜帶參數(shù),表示父進(jìn)程在這個位置要等待p1進(jìn)程執(zhí)行完成后,
#再繼續(xù)執(zhí)行下面的語句,一般用于進(jìn)程間的數(shù)據(jù)同步,如果不寫這一句,
#下面的is_alive判斷將會是True,在shell(cmd)里面調(diào)用這個程序時
#可以完整的看到這個過程,大家可以嘗試著將下面的這條語句改成p1.join(1),
#因為p2需要2秒以上才可能執(zhí)行完成,父進(jìn)程等待1秒很可能不能讓p1完全執(zhí)行完成,
#所以下面的print會輸出True,即p1仍然在執(zhí)行
p1.join()
print("p1.is_alive=%s"%p1.is_alive())
輸出結(jié)果:
進(jìn)程ID:19866
p2.is_alive=True
p1.name=Process-1
p1.pid=19867
p2.name=dongGe
p2.pid=19868
worker_1,父進(jìn)程(19866),當(dāng)前進(jìn)程(19867)
worker_2,父進(jìn)程(19866),當(dāng)前進(jìn)程(19868)
worker_2,執(zhí)行時間為'1.00'秒
worker_1,執(zhí)行時間為'2.00'秒
p1.is_alive=False