python進程

進程是用來運行程序的
python的os模塊封裝了常見的系統調用,其中就包括fork,可以在Linux下輕鬆創建子進程。
fork函數一旦調用成功,系統會產生一個原來進程的克隆,原進程升級爲父進程。
進程的幾個概念:
孤兒進程:
子進程還未運行完成,父進程已經結束,父進程死掉後,子進程會被其他進程託管,通常是init進程(pid=1)
殭屍進程:
子進程已經運行完成,但是父進程未對其進行回收,此時子進程仍佔用着系統資源
守護進程:
守護進程是後臺運行的一些特殊進程:
守護進程在系統引導的時候啓動,並且一直運行直到系統關閉
只在需要的時候才啓動,完成任務後就自動結束
在linux環境下,可以使用os.fork()來生成子進程,子進程會複製一份一模一樣的數據來執行當前程序
os.fork()生成子進程
值得注意的是調用這個會返回一個值,父進程爲子進程的pid號,而子進程的此id爲0,所以我們可以以此來判斷當前運行的是父進程還是子進程
os.getpid()獲取當前進程id
os.getppid()獲取父進程id
下面的例子:

import os
import time

rpid = os.fork()
if rpid < 0:
    print("fork調用失敗。")
elif rpid == 0:
    print("我是子進程(%s),我的父進程是(%s),rpid是(%s)" % (os.getpid(), os.getppid(), rpid))
    print("當前時間是{}".format(time.time()))
else:
    print("我是父進程(%s),我的子進程是(%s),rpid是(%s)" % (os.getpid(), rpid, rpid))
    print("當前時間是{}".format(time.time()))
    time.sleep(1)

如果父進程與子進程運行間隔時間過短可能出現子進程創建失敗的情況,所以加上time.sleep等待一秒再創建子進程
執行結果我是父進程(2655),我的子進程是(2656),rpid是(2656)
當前時間是1524493165.4608128
我是子進程(2656),我的父進程是(2655),rpid是(0)
當前時間是1524493165.4615178方法只在linux上適用,python內置了multiprocessing模塊提供了一個Process類來代表一個進程對象。
創建子進程時,只需要傳入一個執行函數和函數的參數,創建一個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值;

from multiprocessing import Process
import time
import os

def fun():
    print("ppid:{},pid:{},實例id:{}".format(os.getppid(), os.getpid(), p.pid))

p = Process(target=fun, name="testfun")
print("process實例名稱:{}".format(p.name))
p.start()

運行結果:

process實例名稱:testfun
ppid:2864,pid:2865,實例id:2865

可以看到生成的實例進程運行了fun程序

另外一種生成進程的方式,就是用繼承類去創建生成進程,前面說過run方法會在沒有給定target參數時運行,所以我們將方法定義在fun裏就行了

from multiprocessing import Process
import os
import time

class GenProcess(Process):
    def __init__(self):
# 防止name,pid等屬性丟失,直接調用Process初始化屬性
        Process.__init__(self)

    def run(self):
        print("子進程id:{},父進程id:{}".format(os.getpid(), os.getppid()))
        time.sleep(10)

a = GenProcess()
a.start()

運行結果:

子進程id:2913,父進程id:2912

這就是Python生成進程的幾種方式了
當我們需要產生多個進程池,一下循環產生很多進程可能就不那麼好了,這時候就需要進程池了
通過Pool我們可以初始化併發進程數

from multiprocessing import Pool
import time


def genProcess(num):
    print("這是第一種進程{}".format(num))


def genProcess2(num):
    print("這是第二種進程{}".format(num))


# 初始化最大進程數
p = Pool(10)
for i in range(100):
# apply_async爲異步非阻塞,apply爲阻塞
    p.apply_async(genProcess, (i,))
    p.apply_async(genProcess2,(i,))
print("start----")
# 使其不再接受新任務
p.close()
p.join()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章