Python編程之多進程(multiprocessing)詳解

来源:https://www.cnblogs.com/lovefisho/archive/2022/05/05/16202006.html
-Advertisement-
Play Games

HandlerInterceptor源碼 ##3種方法: preHandle:攔截於請求剛進入時,進行判斷,需要boolean返回值,如果返回true將繼續執行,如果返回false,將不進行執行。一般用於登錄校驗。 postHandle:攔截於方法成功返回後,視圖渲染前,可以對modelAndVie ...


引言

multiprocessing是一個用於產生多進程的包,與threading模塊的API類似。multiprocessing既可以實現本地的多進程,也可以實現遠程的多進程。通過使用多個子進程而非線程可以繞開Python的全局解釋器鎖(GIL),同時允許在多種系統平臺使用。

1. Process 模塊

1.1 Process介紹

Process模塊是一個創建進程的模塊,可以通過Process直接創建進程。

multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)


"""
參數介紹:
    
    1. group預設為None(目前未使用)
    2. target代表調用對象,即子進程執行的任務
    3. name為進程名稱
    4. args調用對象的位置參數元組,args=(value1, value2, ...)
    5. kwargs調用對象的字典,kwargs={key1:value1, key2:value2, ...}
6. daemon表示進程是否為守護進程,布爾值
    
方法介紹:
  Process.start() 啟動進程,並調用子進程中的run()方法
  Process.run() 進程啟動時運行的方法,在自定義時必須要實現該方法
  Process.terminate() 強制終止進程,不進行清理操作,如果Process創建了子進程,會導致該進程變成僵屍進程
  Process.join() 阻塞進程使主進程等待該進程終止
  Process.kill() 與terminate()相同
  Process.is_alive() 判斷進程是否還存活,如果存活,返回True
  Process.close() 關閉進程對象,並清理資源,如果進程仍在運行則返回錯誤
  
"""

註意:

  • 在Windows中,由於沒有fork(Linux中創建進程的機制),在創建進程的時候會import啟動該文件,而在import文件的時候又會再次運行整個文件,如果把Process()放在 if __name__ == '__main__' 判斷之外,則Process()在被import的時候也會被運行,導致無限遞歸創建子進程導致報錯,所以在Windows系統下,必須把Process()放在 if __name__ == '__main__' 的判斷保護之下。
  • 在子進程中不能使用input,因為輸入台只顯示在主進程中,故如果在子進程中使用input,會導致報錯。

1.2 Process實例

from multiprocessing import Process


def main(name):
    print(f'{name}: Hello World')


if __name__ == '__main__':
    # 創建子進程
    p = Process(target=main, args=('LovefishO',))
    
    # 開始進程
    p.start()
    
    # 阻塞進程
    p.join()
例子

 

1.3 Process類實現

from multiprocessing import Process


class NewProcess(Process):
    def __init__(self, name):
        
        # 執行父類的init()
        super().__init__()  
        
        # 創建新參數
        self.name = name
    
    # 在自定義Process類時,必須實現run()方法
    def run(self):
        print(f'{self.name}: Hello World')


if __name__ == '__main__':
    
    # 創建一個新的子進程,並傳入參數
    np = NewProcess('LovefishO')
    
    # 開始子進程
    np.start()
    
    # 加入阻塞,保證主進程在子進程之後結束
    np.join()
    
    print('主進程結束')      


# LovefishO: Hello World
# 主進程結束 

 

1.4 守護進程

正常情況下,當子進程和主進程都結束時,程式才會結束。但是當我們需要在主進程結束時,由該主進程創建的子進程也必須跟著結束時,就需要使用守護進程。當一個子進程為守護進程時,在主進程結束時,該子進程也會跟著結束。

 

from multiprocessing import Process


def main(name):
    print(f'{name}: Hello World')


if __name__ == '__main__':
    # 創建守護進程, 設置daemon = True
    p = Process(target=main, daemon=True, args=('LovefishO',))

    # 開始進程
    p.start()

    # 阻塞進程
    p.join()

 

2. Pool 模塊

2.1 Pool介紹

Pool模塊控制著一個進程池,池中是可以執行很多任務的進程

multiprocessing.Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None, context=None)



"""
參數介紹:
    
    processes: 設置要使用的進程數量,如果 processes 為 None,則使用 os.cpu_count() 返回的值
initializer: 是每個工作進程啟動時要執行的可調用對象,預設為None maxtasksperchild: 工作進程退出之前可以完成的任務數,完成後用一個新的工作進程來替代原進程,為了釋放閑置資源 context: 可被用於指定啟動的工作進程的上下文
"""

 

2.2 Pool中分派任務的方式

  • apply(func[, args[, kwds]])方法是阻塞,意味著當前的進程沒有執行完的話,後續的進程需要等待該進程執行結束才能執行,實際上該方法是串列。

  • apply_async(func[, args[, kwds[, callback[, error_callback]]]])方法是非同步非阻塞的,意味著不用等待當前進程執行完成,即可根據系統的調度切換進程,該方法是並行。

  • map(funciterable[, chunksize])方法將iterable對象分成一些塊,作為單獨的任務提交給進程池。 這些塊的(近似)大小可以通過將chunksize設置為正整數來指定, 並且該方法是阻塞的。如果可迭代對象很多時,會消耗較大的記憶體,可以考慮使用imap或imap_unordered。

  • map_async(funciterable[, chunksize[, callback[, error_callback]]])方法是map的變種,是非阻塞的。

  • imap(funciterable[, chunksize])該方法和map一樣,只不過該方法適用於對大量數據的遍歷,返回的結果順序和輸入相同。

  • imap_unordered(funciterable[, chunksize])與imap()一樣,只不過輸出的順序是任意的

 

2.3 Pool實例

from multiprocessing import Pool


def main(name, num):
    print(f'{num} {name}: Hello World')


if __name__ == '__main__':
    # 創建進程池
    p = Pool()

    for i in range(5):
        
        p.apply(func=main, args=('LovefishO', i, ))

    # 關閉進程池
    p.close()

    # 阻塞進程, 等待子進程執行結束
    p.join()

    print('主進程結束')


# 0 LovefishO: Hello World
# 1 LovefishO: Hello World
# 2 LovefishO: Hello World
# 3 LovefishO: Hello World
# 4 LovefishO: Hello World
# 主進程結束
Pool例子

 

3. Queue 模塊

3.1 Queue介紹

 由於進程彼此之間互相隔離,要實現進程間通信,multiprocessing提供了兩種形式:隊列(queue)和管道。隊列可以簡單的理解為一種特殊的列表,可以設置固定的長度,從左邊插入數據,從右邊獲取數據,並滿足先進先出。並且隊列時進程安全的,即同一時刻只有一個進程能夠對隊列進行操作。

multiprocessing.Queue(maxsize)


"""
    參數介紹:
                
          maxsize:設置隊列長度    
    
    方法介紹:
         
          qsize():返回隊列長度,該結果是不可靠的,因為在使用該方法時,隊列中的數據仍在進行刪除增加
          empty():如果隊列為空,則返回True,反之亦然,該狀態不可靠
          full():如果隊列滿了,則返回True,反之亦然,該狀態不可靠
          put(obj[, block[, timeout]]):將obj放入隊列
          get([block[, timeout]]):從隊列中取出並返回對象
close(): 當前進程不會在隊列中放入對象
"""

 

3.2 Queue實例

from multiprocessing import Process, Queue


def product(queue, num):
    # 把obj插入隊列
    queue.put(num)
    print(f'Product {num}')


def consumer(queue):
    # 從隊列中獲取數據
    temp = queue.get()
    print(f'consumer consumed {temp} product')


if __name__ == '__main__':
    # 創建隊列
    q = Queue()
    
    # 生產商品
    for i in range(5):
        p1 = Process(target=product, args=(q, i, ))
        p1.start()

    # 消費生產的商品
    for i in range(5):
        p2 = Process(target=consumer, args=(q,))
        p2.start()
Queue例子

註意:

  • 在使用隊列時(Queue)如果要使用進程池則不能使用multiprocessing.Pool,而是應用使用multiprocessing.Manager().Pool()

3.3 Queue + Pool實例

import multiprocessing


def product(queue, num):
    # 把obj插入隊列
    queue.put(num)
    print(f'Product {num}')


def consumer(queue):
    # 從隊列中獲取obj
    num = queue.get()
    print(f'consumer consumed {num} product')


if __name__ == '__main__':
    # 創建隊列
    q = multiprocessing.Manager().Queue()

    # 創建進程池
    p = multiprocessing.Pool()

    # 生產商品
    for i in range(5):

        p.apply(func=product, args=(q, i,))

    # 消費生產的商品
    for i in range(5):
        p.apply(func=consumer, args=(q,))

    # 關閉進程池
    p.close()

    # 阻塞進程
    p.join()

    print('主進程結束')


# Product 0
# Product 1
# Product 2
# Product 3
# Product 4
# consumer consumed 0 product
# consumer consumed 1 product
# consumer consumed 2 product
# consumer consumed 3 product
# consumer consumed 4 product
# 主進程結束
Queue + Pool例子

 

4. Reference

Multiprocessing官方文檔

參考博客

 

本文來自博客園,作者:LoveFishO,轉載請註明原文鏈接:https://www.cnblogs.com/lovefisho/p/16202006.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JList、JComboBox實現列表框 無論從哪個角度來看, JList 和 JComboBox 都是極其相似的,它們都有一個列表框,只是 JComboBox的列表框需要 以下拉方式顯示出來; JList 和 JComboBox 都可以通過調用 setRendererO方法來改變列表項的表現形式 ...
  • 強類型語言 要求變數的使用嚴格符合規定,所有變數都必須先定義後才能使用 弱類型語言 Java 的數控類型分為兩大類 基本類型(primitive type) 引用類型(reference type) 什麼是位元組 位(bit):是電腦 內部儲存的最小單位,11001100是一個八位二進位數。 位元組( ...
  • 淺嘗Spring註解開發_Spring容器創建概述 淺嘗Spring註解開發,基於Spring 4.3.12 概述Spring容器創建的過程,包括12個方法的執行 淺嘗Spring註解開發_自定義註冊組件、屬性賦值、自動裝配 淺嘗Spring註解開發_Bean生命周期及執行過程 淺嘗Spring註解 ...
  • 聽說10個人去互聯網公司面試,有9個人會被問到緩存雪崩和緩存穿透的問題。 聽說,這9個人裡面,至少有8個人回答得不完整。 而這8個人裡面,全都是在網上找的各種面試資料去應付的,並沒有真正理解。 當然,也很正常,只有大規模應用緩存的架構才會重點關註這兩個問題。 那麼如何真正理解這兩個問題的底層邏輯,我 ...
  • 這個問題老生常談了,大部分互聯網公司的項目都可能會遇到這樣的問題,這裡並不能給到大家一個具體的、徹底的、完美的解決方案,具體的項目、團隊情況需要具體的分析,我這裡記錄一下遇到這種問題時候的一些思考和處理方式吧。 團隊情況 來到新的公司後,擔任XX項目開發組長,主管先讓我帶5個人的團隊:2個前端、2個 ...
  • 需求 要求開發一個hello.go程式,可以輸出helloworld 開發的步驟 (1)開發這個程式/項目時,go的目錄結構怎麼處理 (2)代碼如下: ```go package main import "fmt" func main() { fmt.Println("hello,world") } ...
  • 前言 利用Python製作遠程查看別人電腦的操作記錄,與其它教程類似,都是通過郵件返回。 利用程式得到目標電腦瀏覽器當中的訪問記錄,生產一個文本併發送到你自己的郵箱,當然這個整個過程除了你把python程式植 入目標電腦外,其它的操作都是自動化的。 我知道我說到這些,有些人又開始有其它的想法了,可別 ...
  • #volatile關鍵字 ##什麼是可見性? 可見性是指線程A改變變數的值後,線程B可以馬上看到更改後變數的值 ##volatile的作用 關鍵字volatile提示線程每次從共用記憶體中讀取數據,而不是從私有記憶體中讀取,這樣就保證了同步數據的可見性 ##關鍵字volatile適用的場景 當想實現一個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...