1. 程式人生 > >2018.11.08python學習第三十六天

2018.11.08python學習第三十六天

一:守護程序

# 守護程序:顧名思義,就是一個程序守護著另一個程序,指的是兩個程序之間的關係。
# 特點:就是守護程序在被守護程序死亡時,也會跟著被守護程序的死亡而死亡。
使用方法:
from multiprocessing import Process
import time
def task():
    print('hello')
    time.sleep(3)
    print('see u')
 
if __name__ == '__main__':
    p = Process(target = task)
    p.daemon = True
    p.start()
    time.sleep(3)           #
    print('process is running')
    
# 1.daemon必須在start之前寫
# 2.當主程序死亡時,守護程序也會死亡,如果註釋掉time.sleep(3),守護程序還沒來得及執    行就死亡。

二:互斥鎖

#當多個程序對統一資源進行讀寫時,這些程序會對這個資源產生競爭,從而導致資料錯亂,解決方法就是將這些程序變成序列。那麼我們可以用下面的辦法來解決:
1.join  #把整個程序變成序列,並且順序是固定的。
# 雖然join可以將程序變成序列,但是序列是順序是我們人為固定的,對於這些競爭的程序來說不公# 平,而且,當我們需要部分序列的時候,整個時候join顯然不是很適用
# 那麼由此產生了另一種辦法
2.互斥鎖 # 可以實現並程中的部分序列,
使用方法
from multiprocessing import Process,Lock

def task1(lock):
    lock.acquire()
    for i in range(10000):
        print('===')

def task2(lock):
    lock.acquire()
    for i in range(10000):
        print("===============")
    lock.release()

def task3(lock):
    lock.acquire()
    for i in range(10000):
        print("======================================")
    lock.release()

if __name__ == '__main__':
    mutex = lock()
    p1 = Process(target=task1,args=(mutex,))
    p2 = Process(target=task2,args=(mutex,))
    p3 = Process(target=task3,args=(mutex,))
    
    p1.start()
    p2.start()
    p3.start()
    print('over')
    
# 1.先匯入模組Lock
# 2.建立一個鎖物件 mutex = Lock()
# 3.將程序競爭的資源上鎖
注意:所有的程序上鎖的話必須使用同一把鎖

三:互斥鎖應用

搶票程式
from multiprocessing import Process,Lock
import json,time,random

# file = {"count":1}        # json 格式
def show_ticket(name):
    # 模擬網路延遲
    time.sleep(random.randint(1,5))
    with open ('filename','rt',encoding = 'utf-8') as f:
        data = json.load(f)
        print('%s查看了車票剩餘:%s' %(name,data['count']))
        
def buy_ticket(name):
    with open ('filename','rt',encoding = 'utf-8') as f:
        data = json.load(f)
        if data['count'] > 0:
            data['count'] -=1
            time.sleep(random.randint(1,3))
            time.sleep(random.randint(1,3))
            with open('filename','wt',encoding = 'utf-8') as f1:
                json.dump(data,f1)
                print('%s購票成功' %name)
                
def task(lock,name):
    show_ticket(name)
    lock.acquire()
    buy_ticket(name)
    lock.release()
    

if __name__ == '__main__':
    lock = Lock()
    for i in range(1,11):
        p = Process(target = task,args = (lock,'客戶%s' %i))
        p.start()

四:ipc

# 程序彼此之間互相隔離,要實現程序間通訊(ipc/inter process commucation),
# multiprocessing模組支援兩種形式:佇列和管道,這兩種方式都是使用訊息傳遞的
建立佇列的類(底層就是以管道和鎖定的方式實現的):
# Queue([maxsize]):建立共享程序佇列,Queue是多程序安全的佇列,可以使用Queue實現多進# 程之間的資料傳遞
引數介紹
1.maxsize       #是佇列中允許最大項數,省略則需大小限制
方法一介紹
q = Queue()

1.q.put #方法用以插入資料到佇列中,put方法還有兩個引數可以選擇:blocked和timeout。 # 如果block為True(預設),並且timeout為正值,該方法會阻塞timeout指定的時間,直到 # 該佇列有剩餘的空間。如果超時,會丟擲Queue.Full異常。
# 如果block為False,但是Queue已經滿了,會立即丟擲Queue.Full異常。
2.q.get #方法可以從佇列取走一個元素(注意是取走)。同樣有兩個方法引數可以選擇:block和# timeout.
# 如果blocked為True(預設值),並且timeout為正值,那麼在等待時間內沒有取到任何元素,# 會丟擲Queue.Empty異常。
# 如果blocked為False,有兩種情況存在,如果Queue有一個值可用,則立即返回該值,否則,如# 果佇列為空,則立即丟擲Queue.Empty異常.
3.q.get_nowwait()   # 同q.get(False)
4.q.put_nowwait()   # 同q.put(False)
5.q.empty()     # 呼叫此方法時q為空則返回True,該結果不可靠,如在返回True的過程中又                  添加了專案。
6.q.full()      # 呼叫此方法時q已滿則返回True,該結果不可靠,如在返回True的過程中隊                  列中的專案又被取走了。
7.q.qsize()     # 返回佇列中目前專案正確數量,結果也不可靠,和上述一致。
舉例
from multiprocessing import Queue

# 建立一個佇列
q = Queue()

# 存入資料
q.put('hello)       # 存入str
q.put(['1','2','3'])    # 存入list
q.put(1)            # 存入int

# 讀出資料
print(q.get())
print(q.get())
print(q.get())
      
# 阻塞操作
q = Queue(3)        # 限制存放資料的個數

# 存入資料
q.put('hello',block = False)    # 不阻塞
q.put(['1','2','3'],block = False)  # 不阻塞
q.put(1,block =False)   # 不阻塞

# 此時再存入一個數據q.put('word',block = False) 則會丟擲Queue.Full異常
# 如果是q.put('word',block = True)則不會丟擲異常,會等到Queue有位置後再存入
      
#  取出資料
print(q.get(block=False))
print(q.get(block=False))
print(q.get(block=False))
      
# 此時再取出一個數據print(q.get(block = False)) 則會丟擲Queue.Empty異常
# 如果是print(q.gte(block = True)則不會丟擲異常,會等到Queue有資料後再取走
      
方法二:
# 匯入Manager模組
from multiprocessing import Process,Manager
import time

def task(dic):
    print('subprocess is running')
    li[0] = 1
    print(li)
    
    
if __name__ == "__main__":
    m = Manager()
    # 建立一個公共區域
    li = m.list([100])
    p = Process(target = task,args = (li,))
    p.start()
    time.sleep(3)
    print(li)
    
# m = Manager()只能建立list和dict,其他型別則共享不了