Python之multiprocessing模塊及進程池

進程創建方法

      1. 流程特點

        【1】 將需要子進程執行的事件封裝爲函數

        【2】 通過模塊的Process類創建進程對象,關聯函數

        【3】 可以通過進程對象設置進程信息及屬性

        【4】 通過進程對象調用start啓動進程

        【5】 通過進程對象調用join回收進程

    2. 基本接口使用

Process()

功能 : 創建進程對象

參數 : target 綁定要執行的目標函數

             args 元組,用於給target函數位置傳參

             kwargs 字典,給target函數鍵值傳參

p.start()

功能:啓動進程

注意:啓動進程此時target綁定函數開始執行,該函數作爲子進程執行內容,此時進程真正被創建

p.join([timeout])

功能:阻塞等待回收進程

參數:超時時間

    注意

        【1】使用multiprocessing創建進程同樣是子進程複製父進程空間代碼段,父子進程運行互不影響。

        【2】子進程只運行target綁定的函數部分,其餘內容均是父進程執行內容。

        【3】multiprocessing中父進程往往只用來創建子進程回收子進程,具體事件由子進程完成。

        【4】multiprocessing創建的子進程中無法使用標準輸入

示例1

import multiprocessing as mp
from time import sleep


def fun():
    print("子進程開始")
    sleep(3)
    print("子進程結束")


if __name__ == '__main__':
    # 創建進程對象
    p = mp.Process(target=fun)
    # 啓動進程
    p.start()
    # 回收進程
    p.join()

     示例2

from multiprocessing import Process
import os
from time import sleep


def fun1():
    sleep(4)
    print("喫飯", os.getpid(), os.getppid())


def fun2():
    sleep(2)
    print("睡覺", os.getpid(), os.getppid())


def fun3():
    sleep(5)
    print("打豆豆", os.getpid(), os.getppid())


if __name__ == '__main__':

    fun_list = [fun1, fun2, fun3]
    jobs = []
    for f in fun_list:
        p = Process(target=f)
        jobs.append(p)
        p.start()

    for i in jobs:
        i.join()

    # 總耗時5s

示例3

from multiprocessing import Process
from time import sleep


# 帶參數的進程函數
def worker(sec, name):
    for i in range(3):
        sleep(sec)
        print("I'm %s" % name)
        print("I'm working...")


if __name__ == '__main__':
    # p = Process(target=worker, args=(2, "Baron"))
    p = Process(target=worker, kwargs={"name": "Abby", "sec": 2})
    p.start()
    p.join()

 

    3. 進程對象屬性

p.name 進程名稱

p.pid 對應子進程的PID號

p.is_alive() 查看子進程是否在生命週期

p.daemon 設置父子進程的退出關係

    如果設置爲True則子進程會隨父進程的退出而結束

    要求必須在start()前設置

    如果daemon設置成True 通常就不會使用 join()  

from multiprocessing import Process
from time import sleep, ctime


def tm():
    for i in range(3):
        sleep(2)
        print(ctime())


if __name__ == '__main__':
    p = Process(target=tm)
    print("Name:", p.name)  # Process-1
    print("PID:", p.pid)  # None start()後會生成
    print("is_alive:", p.is_alive())  # False start()後爲 True
    print("daemon:", p.daemon)  # False 默認值是False

自定義進程類

     1. 創建步驟

        【1】 繼承Process

        【2】 重寫 __init__ 方法添加自己的屬性,使用super()加載父類屬性

        【3】 重寫run()方法

    2. 使用方法

        【1】 實例化對象

        【2】 調用start自動執行run方法

        【3】 調用join回收線程

"""
    自定義進程類
"""
from multiprocessing import Process


# 自定義類
class MyProcess(Process):
    def __init__(self, value):
        self.value = value
        super().__init__()  # 加載父類init

    def f1(self):
        print("步驟1")

    def f2(self):
        print("步驟2")

    def run(self):
        self.f1()
        self.f2()


p = MyProcess(2)
p.start()  # 執行run,作爲一個子進程執行
p.join()

進程池實現

代碼示例:day8/pool.py

    1. 必要性

        【1】 進程的創建和銷燬過程消耗的資源較多

        【2】 當任務量衆多,每個任務在很短時間內完成時,需要頻繁的創建和銷燬進程。此時對計算機壓力較大

        【3】 進程池技術很好的解決了以上問題。

    2. 原理

        創建一定數量的進程來處理事件,事件處理完進程不退出而是繼續處理其他事件,直到所有事件全都處理完畢統一銷燬。增加進程的重複利用,降低資源消耗。

    3. 進程池實現

        【1】 創建進程池對象,放入適當的進程

from multiprocessing import Pool

Pool(processes)

功能: 創建進程池對象

參數: 指定進程數量,默認根據系統自動判定

        【2】 將事件加入進程池隊列執行

pool.apply_async(func,args,kwds)

功能: 使用進程池執行 func事件

參數: func 事件函數

            args 元組 給func按位置傳參

            kwds 字典 給func按照鍵值傳參

返回值: 返回函數事件對象

        【3】 關閉進程池

pool.close()

功能: 關閉進程池

        【4】 回收進程池中進程

pool.join()

功能: 回收進程池中進程

"""
    進程池
"""
from multiprocessing import Pool
from time import sleep


def worker(msg):
    sleep(2)
    print(msg)


if __name__ == '__main__':
    # 創建進程池
    pool = Pool(3)
    for i in range(18):
        msg = "Hello %d" % i
        pool.apply_async(worker, (msg,))
    # 結果會每2秒 執行完3個進程
    pool.close()
    pool.join()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章