python進程學習
學習知識點:
1.知識點叫什麽
2.知識點用在哪
3.知識如何實現
一. 進程
1.進程是什麽
進程是cpu分配資源的最小單位
理解:在QQ這個進程裏,傳輸一段文字開啟一個線程,傳輸語音又開啟一個線程。所以運行某個軟件相當於開啟了一個進程。而在這個進程裏,有多個功能來支持QQ正常運行,這些功能又各自占了一條線程。
一個進程管理著多個線程。(一個進程至少帶一個線程)
線程和進程的:
1.單進程單線程:一個人在一個桌子上吃飯
2.單進程多線程:多個人在一個桌子上吃飯
3.多進程單線程:多個人每個人在自己桌子上吃飯
2.進程的狀態
狀態分析:就緒態(運行的條件都已經慢去)執行態(zpu正在執行其他的功能)等待態(等待某些條件滿足,例如一個程序sleep了,此時就處於等待態)
3.進程的作用
實現多個任務同時運行,跟多線程功能基本一致。
1 import multiprocessing # 導包 2 import time 3 4 5 def test1(): 6 while True: 7 print("1------") 8 time.sleep(1) 9 10 11 def test2(): 12 while True:13 print("2------") 14 time.sleep(1) 15 16 17 def main(): 18 # 創建進程,跟創建多線程一致 19 t1 = multiprocessing.Process(target=test1) 20 t2 = multiprocessing.Process(target=test2) 21 22 # 開啟進程 23 t1.start() 24 t2.start() 25 26 27 if __name__ == ‘__main__‘: 28 main()
4.主進程與子進程
子進程開啟會復制主進程一樣的代碼
5.進程和線程的區別
1.進程浪費資源較大,而且一段代碼進程執行的速度明顯比線程慢。
2.進程的資源相互獨立不共享,如需通信需要借助一些方法。 線程資源是共享的,但是也有bug,需要加鎖。
3.進程穩定性好,一個任務掛了,有可能整個進程都掛了,但不會影響其他進程。
二. 進程命令進程
1.查看進程
ps -aux
htop
top
2.殺死進程
kill pid名 kill -9 pid名
關於這個命令,之前詢問別人其之間的區別,有人講kill -9 pid 是刪除所有與進程相關的,我的疑惑就來了,既然進程之間不相互影響,那麽刪的是什麽相關的呢?一個殺死進程的命令,除了進程還能殺死什麽?
於是,我上網查了下,再別人的博客下得到了答案:一般不建議使用 kill -9 pid
kill(默認是-15)的真實含義是, 向進程發送信息,而不是殺死進程。 kill 1234 是向進程1234發送一個SIGTERM信號,有時候 kill 1234 並不能結束這個進程,用kill -9 1234 是真的kill了, kill -9 1234是向1234發送SIGKILL信號
兩句命令的區別:SIGNKILL(9) 的效果是立即殺死進程. 該信號不能被阻塞, 處理和忽略。 SIGNTERM(15) 的效果是正常退出進程,退出前可以被阻塞或回調處理。並且它是Linux缺省的程序中斷信號。
一句話, kill是溫柔地殺, kill -9是霸氣地殺
三. 進程的相關知識
1.pid獲取
1 import multiprocessing 2 import time 3 import os 4 5 6 def test1(): 7 while True: 8 print("1-----") 9 time.sleep(1) 10 print("子進程1",os.getpid()) # 獲取當前進程號 11 print("主進程",os.getppid()) # 獲取主進程的進程號 12 13 14 def test2(): 15 while True: 16 print("2-----") 17 time.sleep(1) 18 print("子進程2",os.getpid()) 19 print("主進程",os.getppid()) 20 21 22 def main(): 23 # 創建進程 24 t1 = multiprocessing.Process(target=test1) 25 t2 = multiprocessing.Process(target=test2) 26 27 # 開啟進程 28 t1.start() 29 t2.start() 30 31 print("主進程", os.getpid()) # 獲取主進程的進程號 32 33 34 if __name__ == ‘__main__‘: 35 main()查看進程pid
主進程 7904 1----- 2----- 子進程1 7560 主進程 7904 1----- 子進程2 6136 主進程 7904 2----- 子進程1 7560 主進程 7904 1----- 子進程2 6136 主進程 7904 2----- 子進程1 7560
2.子進程中不能使用input()函數,主進程會等到子進程結束而結束,線程是用來執行代碼的,進程使用分配資源的,子進程會復制主進程的資源數據,進程之間的數據不共享,進程的執行時無序的。
3.傳參
四. 進程與線程的對比
1.進程是分配資源的單位,線程是程序調度的單位
2.進程運行必定有一個主線程運行
3.全局變量:線程共享全局變量,進程不共享全局變量。
4.加深理解進程與線程的圖片
創建
五. 進程間的通訊
1.使用的技術:Queue隊列
2.作用:讓進程之間可以通訊
import queue # 先進先出 q = queue.Queue() q.put(‘1‘) q.put(‘2‘) q.put(‘3‘) print(q.get()) print(q.get()) print(q.get()) # 後進先出 q = queue.LifoQueue() q.put(‘1‘) q.put(‘2‘) q.put(‘3‘) print(q.get()) print(q.get()) print(q.get()) # 存儲數據時可設置優先級的隊列 q = queue.PriorityQueue() # put進入一個元祖,元祖的第一個元素是優先級,數字越小優先級越高 q.put((20, ‘a‘)) q.put((10, ‘b‘)) q.put((30, ‘c‘)) print(q.get()) print(q.get()) print(q.get())queue的用法
3.使用方式
創建隊列放入數據
獲取數據
# 定義一個隊列 import multiprocessing # 定義一個隊列 # 隊列的作用存取數據 # 隊列中的數據取完就沒了 # 隊列中先存先取 import time queue = multiprocessing.Queue(3) # 存數據 queue.put_nowait("abc") queue.put_nowait("abc") queue.put_nowait("abc") # queue.put_nowait("abc") # print(queue.empty()) # 空是有bug time.sleep(1) # 取 print(queue.get_nowait()) print(queue.get_nowait()) # print(queue.get_nowait()) print(queue.empty()) # 空是有bug # print(queue.get_nowait())BUG代碼不要用
4.案例:一個進程讀一個進程寫,在進程創建前創建進程隊列
import multiprocessing import queue import time def write(queue): # 記得傳參數 """寫數據的函數""" # 通過循環去寫數據 for temp in range(10): queue.put(temp) print(temp) time.sleep(1) def read(queue): """定義一個讀的函數""" data_list = [] # 通過循環去讀數據 while True: if queue.empty(): break data_list.append(queue.get()) print(data_list) def main(): # 定義一個進程隊列 queue = multiprocessing.Queue() # 這個說明沒有限制機器性能 # 創建兩個進程 process_write = multiprocessing.Process(target=write, args=(queue,)) process_read = multiprocessing.Process(target=read, args=(queue,)) # 開啟線程 process_write.start() process_write.join() # 控制寫完讀,保證有數據在讀 process_read.start() if __name__ == ‘__main__‘: main()View Code
打印結果:先順序打印0-9 ,停頓1S,在打印0-9的列表。 0 1 2 3 4 5 6 7 8 9 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
六. 進程池
1.什麽是進程池
python中,進程池內部會維護一個進程序列。當需要時,程序會去進程池中獲取一個進程。
如果進程池序列中沒有可供使用的進程,那麽程序就會等待,直到進程池中有可用進程為止
理解:一個學校有很多教室,不同的班級輪流使用這些教室
內置的一些方法:
apply 從進程池裏取一個進程並同步執行
apply_async 從進程池裏取出一個進程並異步執行
terminate 立刻關閉進程池
join 主進程等待所有子進程執行完畢,必須在close或terminete之後
close 等待所有進程結束才關閉線程池
2.進程池的作用
用來重復利用進程,節省資源
3.同步執行:放個代碼感受一下,創建3個進程,循環執行5次任務,這時三個進程輪流執行這5個任務,問題來了,這三個進程號是不變的,也就是創建幾個進程池裏數字為幾,最多就可以創建幾個進程,不可不填。感受代碼。
同步的特點:一個一個執行我們的任務
1 from multiprocessing import Pool 2 import time 3 import os 4 5 6 def func(): 7 time.sleep(1) 8 print("run",os.getpid()) # 獲取當前進程號 9 10 11 def main(): 12 p1 = Pool(3) # 設定開啟3個進程池 13 for i in range(5): 14 p1.apply(func) # 設定異步執行任務 15 16 17 if __name__ == ‘__main__‘: 18 main()View Code
打印結果: run 7996 run 9560 run 4184 run 7996 run 9560
4.異步執行:所有進程同時執行任務 ,apply_async必須和close()必須和join() 這三個必須一起使用,join()要放在for循環之外
1 from multiprocessing import Pool 2 import time 3 import os 4 5 6 def func(): 7 time.sleep(1) 8 print("run",os.getpid()) 9 10 11 def main(): 12 p1 = Pool(3) # 設定開啟3個進程池 13 for i in range(5): 14 p1.apply_async(func) # 異步,有問題,必須加入join跟close 15 16 p1.close() # 關閉進程池,不在接收新的任務 17 p1.join() # 讓我們的主進程等待進程池完成再結束 18 19 20 if __name__ == ‘__main__‘: 21 main()View Code
打印結果: 前三行同時出現,停頓1S,後面兩行同時出現 run 10512 run 12788 run 1688 run 10512 run 12788
案例:復制文件夾
鏈接:http://blog.csdn.net/chaipp0607/article/details/60779129
並發:看上去像同時發生的,指應用能夠交替執行不同的任務,註意點,能夠處理多個任務,沒說非要同時。
並行:指應用能夠同時執行不同的任務,註意點,必須同時。
兩者區別:一個是交替執行,一個是同時執行。
python進程學習