>如果你打算編寫多進程的服務程序,Unix/Linux無疑是正確的選擇。由于Windows沒有fork調用,難道在Windows上無法用Python編寫多進程的程序?
由于Python是跨平臺的,自然也應該提供一個跨平臺的多進程支持。multiprocessing模塊就是跨平臺版本的多進程模塊。
multiprocessing模塊提供了一個Process類來代表一個進程對象,下面的例子演示了啟動一個子進程并等待其結束:
~~~
#coding=utf-8
from multiprocessing import Process
import os
# 子進程要執行的代碼
def run_proc(name):
print('子進程運行中,name= %s ,pid=%d...' % (name, os.getpid()))
if __name__=='__main__':
print('父進程 %d.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('子進程將要執行')
p.start()
p.join()
print('子進程已結束')
~~~
運行結果:

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