Python 47多進程02

進程PID相關

from multiprocessing import Process
import os


def P1():
    print("this is a P1")
    print("子進程的PID",os.getpid())
    print("子進程的父進程的PID",os.getppid()) # 父進程的PID
def P2():
    print("this is a P2")
if __name__ == '__main__':
    a1 = Process(target=P1,)
    a2 = Process(target=P2,name='hahaha') # 指定進程名稱
    a1.start()
    a2.start()
    print(a1.name) # 進程名稱
    print(a2.name)
    print(a1.pid) # 輸出進程的PID號碼
    print(os.getpid()) # 輸出主進程PID

進程其他方法(結束子進程)

import time
from multiprocessing import Process

def P1():
    time.sleep(5)
    print("process 1")

if __name__ == '__main__':
    a1 = Process(target=P1,)
    a1.start()
    print(a1.is_alive()) # 查看子進程是否還在運行
    time.sleep(1)
    a1.terminate() # 給系統一個結束子進程的信號 返回 None
    time.sleep(1)
    print(a1.is_alive())

進程之間的空間隔離

from multiprocessing import Process
import time
num = int(100)
def p1():
    global num # 聲明變量,要對函數外部變量進行修改
    num = int(10)
    print("子進程中:",num)

print('>>',num)
if __name__ == '__main__':
    a = Process(target=p1,)
    print("=====01")
    a.start()
    print("=====02")
    a.join() #等待子進程運行結束
    print("=====03")
    print(num)
# 輸出的變量值不同 說明進程之間是隔離運行的
主進程中print 執行兩次問題

python 每次執行都會加載默認main函數 子進程執行時會把主進程中的所有代碼當做main(或模塊)加載一遍.所以會有輸出兩邊

守護進程

# 守護進程 一直在後臺運行 主進程一旦結束了 所有的子進程都要結束
import time
from multiprocessing import Process

def p1():
    time.sleep(5)
    print("this is a p1")

if __name__ == '__main__':
    a = Process(target=p1,)
    a.daemon = True # 將該進程設置爲守護進程 必須寫在start 之前 如果主進程結束 那麼子進程也要立即結束
    a.start()

print("主進程結束")

主進程結束並不意味這代碼的結束,而其中的普通子進程還在運行 ,daemon 只是將其設爲守護進程,如果主進程結束,那麼守護進程也會結束,但是普通進程還會繼續運行.

殭屍進程和孤兒進程

殭屍進程:子進程比父進程先結束,但是父進程又沒有回收子進程的資源,子進程成爲一個殭屍進程,所以主進程要等待子進程執行結束,回收子進程的資源.
孤兒進程:父進程被殺死了,子進程沒有了父進程,所有進程都在init進程下,孤兒進程將直接被init進程接管回收.

鎖(互斥鎖,進程鎖,同步鎖)

from multiprocessing import Process,Lock
import json
import time

def p(i,lic):
    # 加鎖 當所有進程運行到這裏的時候 只有一個能搶到這個鎖 其他的執行到此會進行等待
    lic.acquire()
    time.sleep(1)
    print("%s"%i)
    # 解鎖 表示當前結束了 其他的可以繼續來搶了
    lic.release()

if __name__ == '__main__':
    lic = Lock()
    for i in range(10):
        a = Process(target=p,args=(i,lic))
        a.start()

模擬測試搶票代碼

from multiprocessing import Process,Lock
import json
import time

def show_1(i):
    with open ('ticket','r',encoding='utf-8') as f:
        ticket_data = f.read()
    #print(ticket_data)
    #print(eval(ticket_data))
    t_data = eval(ticket_data)
    #print(t_data,type(t_data))
    print('%s查詢剩餘票數:%s'%(i,t_data['count']))

def get_1(i,l1):
# 加鎖
    l1.acquire()
    print("%s開始!"%i)
    with open ('ticket','r',encoding='utf-8') as f:
        ticket_data = f.read()
    t_data = eval(ticket_data)
    if t_data['count'] > 0:
        t_data['count'] -= 1
        print("%s開始搶票"%i)
        time.sleep(0.7)
        with open('ticket','w') as w:
            w.write(str(t_data))
            print("%s搶票成功" % i)
        #json.dump(open('ticket','w'),t_data)
    else:
        print("沒票了")
        #解鎖
    l1.release()
if __name__ == '__main__':
    l1 = Lock()
    for i in range(10):
        p1 = Process(target=show_1,args=(i,))
        #p2 = Process(target=get_1(),)
        p1.start()
    for i in range(10):
        c1 = Process(target=get_1,args=(i,l1))
        c1.start()

數據共享

進程之前空間是隔離的,但是有些情況需要多個進程配合,所以設計進程通信
from multiprocessing import Process,Manager,Lock
import time
def f1(md,i,l2):
# 執行到此處都會等待 並行程序再次串行話 雖然降低了效率但是保證了安全
    l2.acquire()
    print("%s開始!"%i)
    #md['name'] += 1
    tmp = md['name']
    tmp -= 1
    time.sleep(1)
    md['name'] = int(tmp)
    l2.release()
# for 循環創建子進程 並且等待子進程全部執行結束
if __name__ == '__main__':
    plist = []
    l2 = Lock()
    m = Manager()
    # 創建了一個manager類型的字典 用於進程通信數據共享
    md = m.dict({'name':100})
    for i in range(10):
        p = Process(target=f1,args=(md,i,l2))
        p.start()
        plist.append(p)
    #[k.join for k in plist]
    for k in plist:
        k.join()
    print(md['name'])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章