$1 多進程概述
進程是正在執行中的應用程序,一個進程包含了該應用程序的所有信息,如加載數據內存空 間、代碼、程序數據、對象句柄,執行單元等等,一個應用程序根據其功能的多樣性,可以 通過多個進程併發的形式來實現。
計算機中多線程的操作已經可以實現多任務的處理機制了,但是如果涉及到多核 CPU 或者 多個 CPU 的硬件主機,多進程併發編程的實現能比多線程併發機制更加有效的利用和發揮 硬件資源優勢。
$2 python多進程開發
2.1淺談multiprocessing 模塊
PYTHON 內建標準模塊 multiprocessing 對多進程併發編程提供了良好的支持,通過該模塊 的 Process 進程類型,可以很方便的創建和管理多個進程;通過該模塊提供的 Lock|RLock進程鎖類型、Event事件類型 、Condition 條件類型等等也可以很方便的完成進程間同步操作。
和多線程的操作方式類似,多進程的實現方式也提供了面向過程的實現和麪向對象的實現 同時多進程的本地數據共享和通信模式也非常的類似多線程編程
multiprocess 常見屬性和方法
名稱 | 描述 |
---|---|
Process | 進程類型,用於創建和管理進程 |
Lock/RLock | 進程互斥鎖/重用鎖,用於進程同步 |
Event | 進程事件類型,用於進程同 |
Condition | 進程條件類型,用於進程同步 |
Queue | 進程隊列類型,用於多進程數據共享 |
Manager | 進程管理類型,用於多進程數據共享 |
Listener/Client | 進程監聽/客戶端,基於網絡多進程之間的數據共享 |
2.2 多進程的基礎操作
通過多進程的方式進行操作,觀察代碼細節和運行模式
"""
version 1.1.0
author lkk
Email [email protected]
DESC python環境下的多進程
"""
import multiprocessing, os
def main_process():
# 打印信息 展示當前進程編號,父進程編號
print('你好,我是子進程,進程編號:{},父進程編號:{}'.format(os.getpid(), os.getppid()))
if __name__ =='__main__':
proc = multiprocessing.Process(target=main_process)
proc.start()
print('你好,我是主進程,進程編號:{},pycharm工具進程編號:{}'.format(os.getpid(), os.getppid()) )
運行程序,查看運行結果,通過進程編號就能看到主進程和創建的 進程之間的關係:
你好,我是主進程,進程編號:4228,pycharm工具進程編號:5432
你好,我是子進程,進程編號:9360,父進程編號:4228
從運行結果就能發現,main 方法運行的是主進程,通過 multiprocessing 創建的子進程是由 主進程產生的!其中5432 是 pycharm 工具進程->4228 當前程序進程->9360 子進程
2.4多進程面向對象實現
多進程的面向對象的實現方式類似多線程的操作模式 自定義進程類型,繼承系統進程標準類型 multiprocessing.Process 重寫父類的 run()方法,在方法中定義執行代碼 在使用時創建該自定義進程類型的對象,調用對象的 start()方法啓動一個新的進程
"""
version 1.1.0
author lkk
Email [email protected]
DESC python多進程面向對象
"""
import multiprocessing,os
class MyProcess(multiprocessing.Process):
"""自定義一個進程"""
def run(self):
"""對父類的進程處理方法進行重寫"""
print('你好,我是子進程,進程編號:{},父進程編號:{}'.format(os.getpid(), os.getppid()))
if __name__ == '__main__':
print('你好,我是主進程,進程編號:{},pycharm工具進程編號:{}'.format(os.getpid(), os.getppid()))
"""創建並啓動一個進程"""
My_proc = MyProcess()
My_proc.start()
你好,我是主進程,進程編號:11060,pycharm工具進程編號:5432
你好,我是子進程,進程編號:612,父進程編號:11060
看出兩者的區別了麼?
2.5帶參數的多進程:共享?獨佔
多線程的操作模式下我們的全局變量是多個線程共享的,所以多線程併發模式下對於數據的 修改非常危險,那麼多進程模式下數據的處理應該是什麼樣的呢?
通過兩種方式來觀察多進程模式下數據的處理
⚫ 全局變量的數據
⚫ 參數數據
(1) 全局變量:多進程數據處理
"""
version 1.1.0
author lkk
Email [email protected]
DESC python帶參數的多進程
"""
import multiprocessing,time
msg = 3
def ch_numers():
"""定義處理函數,修改全局變量的值"""
global msg
while msg > 0:
msg -= 1
print(multiprocessing.current_process().name, '值改變了', msg)
if __name__ == '__main__':
"""創建兩個進程,同時修改數據"""
for i in range(2):
p = multiprocessing.Process(target=ch_numers)
p.start()
time.sleep(2)
print(multiprocessing.current_process().name, msg)
運行結果截圖
多進程程序執行過程中,如果出現對於當前文件全局變量的修改,出現如上結果是必然的;進程本身就是一個獨立運行的程序,多進程意味着當前程序被執行了多次,每個進程中全局 變量的數據都是互相獨立的。
(2) 參數傳遞:多進程數據處理
"""
version 1.1.0
author lkk
Email [email protected]
DESC 多進程數據處理
"""
import multiprocessing, time
def ch_numbers(msg):
"""定義處理函數,修改全局變量"""
while msg > 0:
msg -= 1
print(multiprocessing.current_process().name, '值發生改變了', msg)
if __name__ == '__main__':
# 創建兩個進程,同時修改數據
msg = 3
for i in range(2):
p = multiprocessing.Process(target=ch_numbers, args=(msg,))
p.start()
time.sleep(2)
print(multiprocessing.current_process().name, msg)
上述程序中,我們將數據存儲在變量 msg 中,通過參數的方式傳遞給進程函數進行執行 執行結果如下:
運行結果截圖
給多進程併發處理函數傳遞參數的方式,並不能讓數據可以被多個進程共享 函數執行併發操作時,每個進程都會單獨拷貝一份當前進程的變量數據進行獨立使用而不互 相影響,這也是出現上述代碼結果的原因 。
2.6多個進程通信:multiprocessing.Manager
不同線程之間的數據通信,涉及到核心的數據共享問題,主要由 PYTHON 中提供的內建模 塊 multiprocessing.Manager 類型實現,該類型內置了大量的用於數據共享的操作
multiprocessing.Manager 常見屬性和方法
2.7 多個進程通信:multiprocessing.Queue
多個進程之間的通信操作,數據的傳遞在 PYTHON 中的 multiprocessing 模塊中提供了一個 專門用於多進程之間進行數據傳遞的隊列:Queue
multiprocessing.Queue 常見屬性和方法
2.8多個進程通信:multiprocessing.Pipe
PYTHON 爲了更加友好的多個進程之間的數據通信操作,提供了一個管道類型專門用於進程之間的協作:multiprocessing.Pipe
multiprocessing.Pipe 常見屬性和方法
名稱 | 描述 |
---|---|
init(duplex=True) | 初始化方法,返回兩個數據 conn1,conn2 分別表示管道的兩端,默認是雙向通信 如果 duplex=False conn1 只能接受消息,conn2 只能發送消息 |
send(data) | 發送消息 |
recv() | 接受消息 |