1. 程式人生 > 其它 >python程序(2)

python程序(2)

python程序

multiprocess模組

'process模組是一個建立程序的模組,藉助這個模組,就可以完成程序的建立'
Process([group [, target [, name [, args [, kwargs]]]]])
#引數介紹:

1 group引數未使用,值始終為None
2 target表示呼叫物件,即子程序要執行的任務
3 args表示呼叫物件的位置引數元組,args=(1,2,'egon',)
4 kwargs表示呼叫物件的字典,kwargs={'name':'egon','age':18}
5 name為子程序的名稱

#強調:
1. 需要使用關鍵字的方式來指定引數
2. args指定的為傳給target函式的位置引數,是一個元組形式,必須有逗號

multiprocess模組方法

#p.start()
啟動程序,並呼叫該子程序中的p.run() 

#p.run()
程序啟動時執行的方法,正是它去呼叫target指定的函式,我們自定義類的類中一定要實現該方法  

#p.terminate()
強制終止程序p,不會進行任何清理操作,如果p建立了子程序,該子程序就成了殭屍程序,使用該方法需要特別小心這種情況。如果p還儲存了一個鎖那麼也將不會被釋放,進而導致死鎖

#p.is_alive():
如果p仍然執行,返回True

#p.join([timeout])
主執行緒等待p終止(強調:是主執行緒處於等的狀態,而p是處於執行的狀態)。timeout是可選的超時時間,需要強調的是,p.join只能join住start開啟的程序,而不能join住run開啟的程序 

join方法

# 程式碼示例:
import time
from multiprocessing import Process

def func():
    print("子程序開始執行!")
    time.sleep(1)
    print("子程序執行完畢!")

if __name__ == '__main__':
    print("主程序開始執行!")
    p = Process(target=func, )
    p.start()
    p.join()
    print("主程序執行完畢!")

# 執行結果:   
	主程序開始執行!
	子程序開始執行!
	子程序執行完畢!
	主程序執行完畢!

'當主程序執行到p.join()時,整個程式會阻塞在這裡,直到子程序p執行完畢,主程序才能繼續向下執行,也就不會出現主程序先於子程序執行完畢的現象了'

程式碼建立程序

第一種建立程序的方式

# 程式碼示例
from multiprocessing import Process

def dask(name):
    print("%s的子程序"%name)


if __name__ == '__main__':
    p = Process(target=dask, args=('kevin',)) # 建立一個程序物件
    
    p.start() # 告訴作業系統建立一個新的程序
    
    print('主程序')
    """
強調:不同的作業系統建立程序的要求不一樣
    在windows中建立程序是以匯入模組的方式進行 所以建立程序的程式碼必須寫在__main__子程式碼中
    否則會直接報錯 因為在無限制建立程序
    在linux和mac中建立程序是直接拷貝一份原始碼然後執行 不需要寫在__main__子程式碼中
"""

第二種繼承的形式建立程序

'自定義一個類,繼承Process類,必須寫一個run()方法.如果想要傳參,可以自己寫一個init方法,然後首先執行super父類的init方法,再寫自己的屬性'
# 程式碼示例
from multiprocessing import Process

class MyProcess(Process):   # 自定義的類要繼承Process類
    def __init__(self, n, name):
        super().__init__()  
 # 如果自己想要傳參name, 那麼要首先用super()執行父類的init方法
        self.n = n
        self.name = name
    def run(self):
        print("子程序的名字是>>>", self.name)
        print("n的值是>>>", self.n)

if __name__ == '__main__':
    p1 = MyProcess(123, name="子程序01")
    p1.start()  
    # 給作業系統傳送建立程序的指令,子程序建立好之後,要被執行,執行的時候就會執行run方法
    print("p1.name是>>>", p1.name)
    print("主程序結束")

# 執行結果:
# p1.name是>>> 子程序01
# 主程序結束
# 子程序的名字是>>> 子程序01
# n的值是>>> 123

程序實現併發

"""
將與客戶端通訊的程式碼封裝成一個函式 
之後每來一個客戶端就建立一個程序專門做互動
"""
# 程式碼示例:
'將服務端的程式碼封裝成函式'
def get_server():
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    return server
'''封裝一個get_server,這個建立程序就不會反覆執行裡面的程式碼
從而避免報地址只允許使用一次的錯誤'''

def talk():
    while True:
        data = socket.recv(1024)
        print(data.decode('utf8'))
        sock.send(data)

if __name__ == '__main__':
    server = get_server()
    while True:
        sock, addr = server.accept()
        p = Process(target=talk,args=(sock,))
        p.start()
        

程序間資料預設隔離

'程序之間是空間隔離的,不共享資源'
#程式碼示例:
import time
from multiprocessing import Process

global_num = 100
def func():    # 子程序
    global global_num
    global_num = 0
    print("子程序的全域性變數>>>", global_num)

if __name__ == '__main__':
    p1 = Process(target=func,)
    p1.start()
    time.sleep(1)  # 等待子程序執行結束
    print("主程序的全域性變數>>>", global_num)

# 執行結果:
	子程序的全域性變數>>> 0
	主程序的全域性變數>>> 100


程序物件屬性

#程式碼示例:
from multiprocessing import Process

def dask(name):
    print("%s的子程序"%name)

if __name__ == '__main__':
    p = Process(target=dask, args=('jason',))
    p.start()
    p.join()
    print("子程序的ID是>>>", p.pid)
    print("子程序的名字是>>>", p.name)
    print("主程序執行完畢!")
    
   """
程序號如何檢視
	windows: 			tasklist結果集中PID
	mac:					ps -ef
"""
#檢視程序號的方法
1.current_process函式
  	from multiprocessing import Process, current_process
    current_process().pid
 	# 獲取程序號的用處之一就是可以通過程式碼的方式管理程序
  	windows  			taskkill關鍵字
    mac/linux  		kill關鍵字
2.os模組
  	os.getpid()  # 獲取當前程序的程序號
    os.getppid()  # 獲取當前程序的父程序號
    

殭屍程序與孤兒程序

# 殭屍程序
	 '為什麼主程序預設需要等待子程序結束才會結束'
  所有的子程序在執行結束之後都會變成殭屍程序(死了沒死透)
  還保留著pid和一些執行過程的中的記錄便於主程序檢視(短時間儲存)
  這些資訊會被主程序回收(殭屍徹底死了)
  	1.主程序正常結束
    2.呼叫join方法
    
# 孤兒程序
	# 子程序存活著 父程序意外死亡
  子程序會被作業系統自動接管(兒童福利院)

守護程序

'主程序執行結束,由該主程序建立的子程序必須跟著結束'
# 程式碼示例
from multiprocessing import Process
import time
def dask(name):
    print("%s開始執行子程序" % name)
    time.sleep(2)
    print("%s結束執行子程序" % name)

if __name__ == '__main__':
    p = Process(target=dask, args=('jason',))
    p.daemon = True
'一定要在p.start()前設定p為守護程序,禁止p建立子程序,並且父程序程式碼執行結束,p即終止執行'
    p.start()
    print("主程序執行完畢!")
    

互斥鎖

# 程式碼示例
import json
from multiprocessing import Process
import time
import random


# 查票
def search(name):
    with open(r'ticket_data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    print(f'{name}查詢當前餘票:%s' % data.get('ticket_num'))


# 買票
def buy(name):
    '''
    點選買票是需要再次查票的 因為期間其他人可能已經把票買走了
    '''
    # 1.查票
    with open(r'ticket_data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    time.sleep(random.randint(1, 3))
    # 2.判斷是否還有餘票
    if data.get('ticket_num') > 0:
        data['ticket_num'] -= 1
        with open(r'ticket_data.json', 'w', encoding='utf8') as f:
            json.dump(data, f)
        print(f'{name}搶票成功')
    else:
        print(f'{name}搶票失敗 沒有餘票了')


def run(name, mutex):
    search(name)
    mutex.acquire()  # 搶鎖
    buy(name)
    mutex.release()  # 放鎖


# 模擬多人同時搶票
if __name__ == '__main__':
    mutex = Lock()
	'互斥鎖需要產生在主程序 然後再交給多個子程序'
    for i in range(1, 10):
        p = Process(target=run, args=('使用者:%s' % i,mutex))
        p.start()

'''當多個程序操作同一份資料的時候會造成資料的錯亂!!!
這個時候需要加鎖處理(互斥鎖)
	將併發變成序列 犧牲了效率但是保證的資料的安全
 
互斥鎖並不能輕易使用 容易造成死鎖現象
互斥鎖只在處理資料的部分加鎖 不能什麼地方都加 嚴重影響程式的效率'''