Python 多進程并發(fā)網絡編程

2018-08-18


psbZIOJOYAH.jpg

進程(Process):
  計算機中正在進行的應用程序叫做進程。一個進程包含了該應用程序的所有信息,如加載數(shù)據內存空間、代碼、程序數(shù)據、對象句柄、執(zhí)行單元等等。
  計算機中多線程的操作已經實現(xiàn)了多任務的處理機制了,但是多核CPU下的多進程并發(fā)編程的實現(xiàn),能比多線程并發(fā)機制更加有效的利用和發(fā)揮硬件優(yōu)勢。

Python中的multiprocessing模塊,可以實現(xiàn)多進程并發(fā)編程。
import multiprocessing?。DK中常見的屬性和方法

名稱        作用
.Process    # 進程類型用于創(chuàng)建、管理一個進程
.Lock/Rloak    # 進程互斥鎖/重用鎖,用于進程同步
.Event    # 進程事件類型,用于進程同步
.Condition    # 進程條件類型,用于進程同步
.Queue    # 進程隊列類型,用于多進程數(shù)據共享
.Manager    # 進程管理類型,多進程數(shù)據共享
.Listener|Client    # 進程監(jiān)聽|客戶端,基于網絡多進程之間的數(shù)據共享

1、多進程的基本操作
 1.1 創(chuàng)建一個面向過程的函數(shù)式進程

import multiprocessing, time, os

def hello_world():
  # 輸出信息, 展示當前進程編號,  父進程編號     
   print("hello myname is process", os.getpid(),os.getppid()) 
 
if __name__ == "__main__":      
   proc = multiprocessing.Process(target=hello_process)  # 創(chuàng)建一個進程     

   proc.start()    ?。舆M程
  
     print("hello, i ma main:", os.getpid(), os.getppid()) 

運行程序,查看運行結果,通過進程編號就能看到主進程和創(chuàng)建的進程之間的關系:

hello , i  am main : 2456 2772 
hello my name is process 13536 2456 

從運行結果就能發(fā)現(xiàn),main 方法運行的是主進程,通過multiprocessing 創(chuàng)建的子進程是由主進程產生的!
其中 2772 是 pycharm 工具進程創(chuàng)建的程序主進程
->2456 當前程序進程
->13536 子進程

1.2 面向對象的面向對象編程-_-||
  多進程的面向對象,的實現(xiàn)方式,類似多線程的操作模式
  自定義進程類型:繼承系統(tǒng)進程標準類型multiprocessing.Process
  重寫父類的run()方法,在方法中定義執(zhí)行代碼,run方法不用調用,會自動執(zhí)行!!
  在使用時創(chuàng)建自定義進程類型的對象,調用對象的start()方法啟動一個新的進程

import multiprocessing, os

class My_process(multiprocessing.Process):
  '''自定義一個進程類型'''
  def run(self):      # 重寫run方法
    print("hello, my name id process", os.getpid(), os.getppid())

if __name__ == "__main__":
  print("hello, my name is main", os.,getpid(), os.getppid())
  # 創(chuàng)建一個進程
  my_proc = Myprocess()
 ?。右粋€進程
  my_proc.start()

執(zhí)行結果,和函數(shù)式編程的結果相同:

hello, my name is main: 7048 2772
hello, my name is process: 3140 7048 
  1. 多進程模式下的數(shù)據操作
     ?。ǘ嗑€程的操作模式下,全局變量十多個線程共享的。所以多線程并發(fā)模式下對于數(shù)據的修改非常危險?。?br>   多進程模式下,全局變量的參數(shù)是不共享的。在執(zhí)行代碼時,全局變量的值會被進程復制到進程自己的代碼塊里執(zhí)行,全局變量的參數(shù)是不會變的??!
    代碼見下方:
import multiprocessing, time

# 定義全局變量
bl = 3

# 定義進程函數(shù)
def change_num():
    global bl
    while bl > 0:
        bl -= 1
        print(multiprocessing.Process().name, '進程里的全局變量:', bl)

if __name__ == "__main__":
    # 創(chuàng)建兩個進程,并修改數(shù)據
    for i in range(2):
        p = multiprocessing.Process(target = change_num)
        p.start()

    time.sleep(2)
    print("這是全局變量", bl)

運行結果如下:

Process-1:1 進程里的全局變量: 2
Process-1:2 進程里的全局變量: 1
Process-1:3 進程里的全局變量: 0
Process-2:1 進程里的全局變量: 2
Process-2:2 進程里的全局變量: 1
Process-2:3 進程里的全局變量: 0
這是全局變量 3

可以發(fā)現(xiàn)進程里的全局變量的值雖然發(fā)生了變化,
但是外部全局變量的值沒有改變?。?/p>

  1. 多進程的簡化:內置進程池
       通過進程池Pool,可以快速創(chuàng)建多個進程執(zhí)行指定函數(shù),完成餡餅發(fā)處理操作

Pool的屬性和方法:

名稱           作用
apply(func, args)   #args-要傳遞參數(shù), func-要執(zhí)行的函數(shù)名稱,同時阻塞當前進程知道該函數(shù)執(zhí)行完成。
             函數(shù)func只會在進程池中的一個進程池運行
---------------------------------------------------
#該方法不會形成阻塞
apply_async(func, args, callback, error_callback)
func        ?。╝rgs-要傳遞參數(shù), func-要執(zhí)行的函數(shù)名稱
args         函數(shù)執(zhí)行完成之后可以通過結果對象的 get()方法獲取結果 )
callback        #如果結果對象可用時會自動調用 callback 指定的函數(shù)
error_callback     #如果結果對象調用失敗時會自動調用 error_callback 指定的函數(shù)
---------------------------------------------------
.close()   #Pool 進程池的底層工作機制是向進程池提交任務產生工作進程執(zhí)行 
        該方法是主動停止給進程池提交任務,并等待所有提交任務執(zhí)行完成退出 
.terminate()   #立即結束該進程,當進程池對象被回收時自動調用該方法 
.join()     # 等待工作進程退出,再次之間必須調用 close()或者 teminate 

實例如下:

import multiprocessing, time, os

def my_proc():
    print(multiprocessing.current_process().name, "一個進程正在工作", os.getppid(), os.getpid())
    time.sleep(1)


if __name__ == "__main__":
    # 創(chuàng)建一個進程池
    pool = multiprocessing.Pool(2)

    # 循環(huán)任務
    for i in range(20):
        pool.apply_async(my_proc)

    # 停止提交任務
    pool.close()
    # 獨占執(zhí)行
    pool.join()

結果如下:

SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100
SpawnPoolWorker-2 一個進程正在工作 11596 13680
SpawnPoolWorker-1 一個進程正在工作 11596 14100

Process finished with exit code 0

可以發(fā)現(xiàn)進程池里的兩個進程處理了循環(huán)的8個任務

  1. 多個進程通信,即數(shù)據實現(xiàn)共享(待實際操作)
      Python中提供了multiprocessing.Manager類型,該類型內置了大量的用于實現(xiàn)數(shù)據共享的操作

常見的屬性和方法:

名稱           描述
Array          內置進程間共享 數(shù)組 類型
Queue          內置進程間共享 隊列 類型
list()          內置進程間共享 列表 類型
dict()          內置進程間共享 字典 類型
value          內置進程間共享 值 類型

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 本文是我自己在秋招復習時的讀書筆記,整理的知識點,也是為了防止忘記,尊重勞動成果,轉載注明出處哦!如果你也喜歡,那...
    波波波先森閱讀 11,621評論 4 56
  • 必備的理論基礎 1.操作系統(tǒng)作用: 隱藏丑陋復雜的硬件接口,提供良好的抽象接口。 管理調度進程,并將多個進程對硬件...
    drfung閱讀 3,763評論 0 5
  • 1.ios高性能編程 (1).內層 最小的內層平均值和峰值(2).耗電量 高效的算法和數(shù)據結構(3).初始化時...
    歐辰_OSR閱讀 30,246評論 8 265
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,665評論 1 32
  • 我進入房間之后,首先去翻了我父母的床頭柜,可是很失望,里面只有賬單、首飾、看了一部分的雜志、一些保健的藥品和零散的...
    AgLian閱讀 259評論 0 0

友情鏈接更多精彩內容