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
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...