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