1. 程式人生 > >Python爬蟲之多進程淺談

Python爬蟲之多進程淺談

args inf 創建進程 平臺 fifo 概念 實體 異步執行 sin

一、進程及狀態

  1、進程

    程序,是指靜態,而進程則是動態的概念,首先把程序運行起來,代碼+涉及的資源=進程,它是操作系統分配資源的基本單位,多進程可以實現多任務

  2、進程的狀態

    1、就緒態:一切準備好,只等待CPU的調度

    2、運行態:CPU正在執行本進程的代碼

    3、等待態:等待某個條件的滿足,比如sleep,socket.recvfrom,互斥鎖的解鎖,等待紅綠燈,條件滿足則進入就緒態

二、進程的創建-multiprocessing(重點)

  1、multiprocessing模塊介紹:multiprocessing模塊就是跨平臺版本的多進程模塊,提供了一個Process類來創建進程對象

  2、通過multiprocessing模塊創建子進程

    實現步驟:

      1、導入multiprocessing模塊

       2、準備用於封裝任務的函數

       3、通過multiprocessing.Process()創建子進程target=function

       4、執行子進程

       參考代碼如下:

            技術分享圖片

            技術分享圖片

  3、獲取進程的id

    a>通過Linux命令方式查看進程id:ps -aux | grep ‘02-’

    b>通過代碼方式查看進程id

        當前的子進程是有主進程創建的

        os.getpid():取得當前進程的id

        os.getppid():取得父進程id(創建當前進程的進程id)

        print("------in main -----當前進程id=%d,父進程id=%d“%(os.getpid(), os.getppid()))

  

4. Process語法結構
a> Process([group [, target [, name [, args [, kwargs]]]]])
"""Process初始化參數"""
- target: 目標,指向, 表示子進程要執行的代碼在target指向的函數中
- args:向target指向的函數傳遞不定參數, 以元組類型來封裝這些不定參數
- kwargs:向target指向的函數傳遞關鍵字參數,以字典類型來封裝這些關鍵字參數

b> 進程對象常用的屬性、方法
- process.name: 進程的名稱
- process.pid: 進程的id
- process.start() : 執行進程
- process.is_alive(): 進程是否是活的
- process.join(timeout) : 阻塞當前進程(主進程),等待子進程執行完畢,再解阻塞
# timeout=2 : 最多阻塞主進程2秒,超過2秒,則主進程解阻塞
- process.terminate() :結束子進程的執行


參考代碼: 03-向子進程傳遞參數.py
參考代碼: 04-進程的屬性和方法.py

5. 進程間不共享全局變量
進程間不共享全局變量
參考代碼: 05-進程間不共享全局變量.py

三、進程線程對比

a>功能方面
都能完成多任務
b>定義方面
1. 進程是操作系統進行資源分配和調度的一個基本單位.
2.線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.

c>區別
1. 一個程序至少有一個進程,一個進程至少有一個線程.
2.線程的劃分尺度小於進程(資源比進程少),使得多線程程序的並發性高。
3.進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率
4.線程不能夠獨立執行,必須依存在進程中

d>優缺點
線程和進程在使用上各有優缺點:線程執行開銷小,但不利於資源的管理和保護;而進程正相反
目標的理解: 要實現多任務, 開多線程比開多進程要更好

四、進程間通信-Queue(隊列)

1.隊列介紹
常用的數據結構,采用先進先出原則(fifo: first inter first outer),從隊列的尾部存(put)數據
從隊列的頭部取(get)數據

2. Queue 的使用
a> queue基本使用
- multiprocess.Queue(maxsize=3)
創建隊列對象,maxsize : 設置隊列存數據的上限,假如不設置maxsize, 則沒有上限的要求
- put(item)
向隊列存數據,假如當前隊列滿,則等待
- get()
從隊列取數據,假如當前隊列空,則等待
- full(): 判隊列是否滿
- empty(): 判隊列是否空

參考代碼: 06-隊列queue初體驗.py

b> 使用Queue隊列實現進程間通信
案例需求: 在父進程中創建兩個子進程,一個往Queue裏寫數據p,y,t,h,o,n一個從Queue裏讀取數據,實現進程間通信

參考代碼: 07-通過隊列實現進程間通信.py

五、進程的創建-進程池Pool
1. 進程池作用
控制進程的數量,重復利用進程對象,減少創建和銷毀進程的開銷
2. 進程池體驗
1. multiprocessing.Pool()
創建進程池對象,可以設置進程池的最大值
2. apply_async(func[,args[,kwds]])
apply(func[,args[,kwds]])
申請異步執行任務
- func: 指向要執行的函數
- args:向要執行的函數傳遞可變參數
- kwds:向要執行的函數傳遞命名參數
3. close() : 關閉進程池, 不再接收新的任務請求
4. terminate() : 結束進程池中的所有子進程,
5. join(): 阻塞當前進程(主進程),等到進程池中的所有進程執行完畢後,再解阻塞

提示(拓展):
進程池的子進程都是由主進程創建的
且默認都是守護進程
假如要執行完進程池中子進程的任務
必須做:
pool.close()
pool.join() # 阻塞主進程

參考代碼: 08-進程池體驗.py

3. 進程池中的進程通信
案例需求: 從進程池中子進程,一個往Queue裏寫數據i,t,c,a,s,t一個從Queue裏讀取數據,實現進程池進程間的通信

提示:如果要使用Pool創建進程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue()

             

Python爬蟲之多進程淺談