亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

python實現多進程通信實例分析

 更新時間:2019年09月01日 08:19:00   作者:alpha_panda  
這篇文章主要介紹了python實現多進程通信實例分析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

操作系統會為每一個創(chuàng)建的進程分配一個獨立的地址空間,不同進程的地址空間是完全隔離的,因此如果不加其他的措施,他們完全感覺不到彼此的存在。那么進程之間怎么進行通信?他們之間的關聯是怎樣的?實現原理是什么?本文就來借助Python簡單的聊一下進程之間的通信?還是那句話,原理是相同的,希望能透過具體的例子來體會一下本質的東西。

下面盡量以簡單的方式介紹一下每一類通信方式,具體的細節(jié)可以參照文檔使用;

1. 管道

先來看一下最簡單、古老的一種IPC:管道。通常指的是無名管道,本質上可以看做一種文件,只存在于內存當中,不會存盤。不同進程通過系統提供的接口來向管道中讀取或者寫入數據。

也就是說我們通過這樣一個中間介質為進程提供交流的方式。無名管道的局限在于一般只用于有直接關聯關系的父子進程。下面通過一個簡單的例子來看一下其用法。

from multiprocessing import Process, Pipe

def pstart(pname, conn):
  conn.send("Data@subprocess")
  print(conn.recv())     # Data@parentprocess

if __name__ == '__main__':
  conn1, conn2 = Pipe(True)
  sub_proc = Process(target=pstart, args=('subprocess', conn2,))
  sub_proc.start()
  print (conn1.recv())    # Data@subprocess
  conn1.send("Data@parentprocess")
  sub_proc.join()

管道通信三步曲:

  1. 創(chuàng)建Pipe,得到兩個connection對象conn1和conn2;
  2. 父進程持有conn1,將conn2傳遞給子進程;
  3. 父子進程通過對持有的connection對象進行send和recv操作以進行數據傳遞和接受;

上面我們創(chuàng)建的是全雙工管道,也可以創(chuàng)建半雙工管道,具體使用可以參照官網描述:

Returns a pair (conn1, conn2) of Connection objects representing the ends of a pipe.

If duplex is True (the default) then the pipe is bidirectional. If duplex is False then the pipe is unidirectional: conn1 can only be used for receiving messages and conn2 can only be used for sending messages.

2. 具名管道(FIFO)

上面介紹的管道主要用于有直接關系的進程,局限性比較大。下面來看一下可以在任意進程間進行通信的具名管道。

由于window平臺上os模塊沒有mkfifo屬性,因此這個例子只能在linux上運行(測試環(huán)境 CentOS 7, Python 2.7.5):

#!/usr/bin/python
import os, time
from multiprocessing import Process

input_pipe = "./pipe.in"
output_pipe = "./pipe.out"

def consumer():
  if os.path.exists(input_pipe):
    os.remove(input_pipe)
  if os.path.exists(output_pipe):
    os.remove(output_pipe)

  os.mkfifo(output_pipe)
  os.mkfifo(input_pipe)
  in1 = os.open(input_pipe, os.O_RDONLY)    # read from pipe.in
  out1 = os.open(output_pipe, os.O_SYNC | os.O_CREAT | os.O_RDWR)
  while True:
    read_data = os.read(in1, 1024)
    print("received data from pipe.in: %s @consumer" % read_data)
    if len(read_data) == 0:
      time.sleep(1)
      continue

    if "exit" in read_data:
      break
    os.write(out1, read_data)
  os.close(in1)
  os.close(out1)

def producer():
  in2 = None
  out2 = os.open(input_pipe, os.O_SYNC | os.O_CREAT | os.O_RDWR)

  for i in range(1, 4):
    msg = "msg " + str(i)
    len_send = os.write(out2, msg)
    print("------product msg: %s by producer------" % msg)
    if in2 is None:
      in2 = os.open(output_pipe, os.O_RDONLY)    # read from pipe.out
    data = os.read(in2, 1024)
    if len(data) == 0:
      break
    print("received data from pipe.out: %s @producer" % data)
    time.sleep(1)

  os.write(out2, 'exit')
  os.close(in2)
  os.close(out2)

if __name__ == '__main__':
  pconsumer = Process(target=consumer, args=())
  pproducer = Process(target=producer, args=())
  pconsumer.start()
  time.sleep(0.5)
  pproducer.start()
  pconsumer.join()
  pproducer.join()

運行流程如下:

每一輪的過程如下:

  1. producer進程往pipe.in文件中寫入消息數據;
  2. consumer進程從pipe.in文件中讀入消息數據;
  3. consumer進程往pipe.out文件中寫入回執(zhí)消息數據;
  4. producer進程從pipe.out文件中讀出回執(zhí)消息數據;

結果如下:

[shijun@localhost python]$ python main.py
------product msg: msg 1 by producer------
received data from pipe.in: msg 1 @consumer
received data from pipe.out: msg 1 @producer
------product msg: msg 2 by producer------
received data from pipe.in: msg 2 @consumer
received data from pipe.out: msg 2 @producer
------product msg: msg 3 by producer------
received data from pipe.in: msg 3 @consumer
received data from pipe.out: msg 3 @producer
received data from pipe.in: exit @consumer

兩個進程沒有直接的關系,每個進程有一個讀文件和寫文件,如果兩個進程的讀寫文件是關聯的,就可以進行通信。

3. 消息隊列(Queue)

進程之間通過向隊列中添加數據或者從隊列中獲取數據來進行消息數據的傳遞。下面是一個簡單的例子。

from multiprocessing import Process, Queue
import time

def producer(que):
  for product in ('Orange', 'Apple', ''):
    print('put product: %s to queue' % product)
    que.put(product)
    time.sleep(0.5)
    res = que.get()
    print('consumer result: %s' % res)

def consumer(que):
  while True:
    product = que.get()
    print('get product:%s from queue' % product)
    que.put('suc!')
    time.sleep(0.5)
    if not product:
      break

if __name__ == '__main__':
  que = Queue(1)
  p = Process(target=producer, args=(que,))
  c = Process(target=consumer, args=(que,))
  p.start()
  c.start()
  p.join()
  c.join()

這個例子比較簡單,queue的具體用法可以參考一下官網。

結果:

put product: Orange to queue
consumer result: suc!
put product: Apple to queue
consumer result: suc!
put product: to queue
consumer result: suc!
get product:Orange from queue
get product:Apple from queue
get product: from queue

這里有幾點需要注意下:

  1. 可以指定隊列的容量,如果超出容量會有異常:raise Full;
  2. 默認put和get均會阻塞當前進程;
  3. 如果put沒有設置成阻塞,那么可能自己從隊列中取出自己放入的數據;

4. 共享內存

共享內存是一種常用的,高效的進程之間的通信方式,為了保證共享內存的有序訪問,需要對進程采取額外的同步措施。

下面的這個例子僅僅簡單的演示了Python中如何在不同進程間使用共享內存進行通信的。

from multiprocessing import Process
import mmap
import contextlib
import time

def writer():
  with contextlib.closing(mmap.mmap(-1, 1024, tagname='cnblogs', access=mmap.ACCESS_WRITE)) as mem:
    for share_data in ("Hello", "Alpha_Panda"):
      mem.seek(0)
      print('Write data:== %s == to share memory!' % share_data)
      mem.write(str.encode(share_data))
      mem.flush()
      time.sleep(0.5)

def reader():
  while True:
    invalid_byte, empty_byte = str.encode('\x00'), str.encode('')
    with contextlib.closing(mmap.mmap(-1, 1024, tagname='cnblogs', access=mmap.ACCESS_READ)) as mem:
      share_data = mem.read(1024).replace(invalid_byte, empty_byte)
      if not share_data:
        """ 當共享內存沒有有效數據時結束reader """
        break
      print("Get data:== %s == from share memory!" % share_data.decode())
    time.sleep(0.5)


if __name__ == '__main__':
  p_reader = Process(target=reader, args=())
  p_writer = Process(target=writer, args=())
  p_writer.start()
  p_reader.start()
  p_writer.join()
  p_reader.join()

執(zhí)行結果:

Write data:== Hello == to share memory!
Write data:== Alpha_Panda == to share memory!
Get data:== Hello == from share memory!
Get data:== Alpha_Panda == from share memory!

下面簡單的來說明一下共享內存的原理;

進程虛擬地址到物理地址的一個映射關如下:

上面這個圖已經很明白的展示了共享內存的原理。

左邊是正常情況下,不同進程的線性地址空間被映射到不同的物理內存頁,這樣不管其他進程怎么修改物理內存,都不會影響到其他進程;

右邊表示的是進程共享內存的情況下,不同進程的部分線性地址會被映射到同一物理頁,一個進程對這個物理頁的修改,會對另一個進程立即可見;

當然潛在的問題就是要采取進程同步措施,也就是對共享內存的訪問必須是互斥的。這個可以借助信號量來實現。

5. socket通信

最后再來介紹一種可以跨主機的進程間通信:socket。

懂網絡編程的人,對這個應該都比較熟悉。socket不僅可以跨主機進行通信,甚至有時候可以使用socket在同一主機的不同進程間進行通信。

這部分代碼比較簡單常見,這里僅僅使用流程圖來表示一下socket通信的流程及相關接口。

上圖表示客戶端上某進程使用socket和服務器上監(jiān)聽程序進行socket通信的一個流程。

小結

到這里關于常見的進程間通信相關的概念和實例均簡單介紹了一下。希望本文能讓你對進程間通信有一個更深入的理解和認識。

結合之前幾篇介紹線程、進程概念及線程間同步的一些措施的介紹,相信應該對線程和進程相關概念有一個簡單清晰的認識了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • windows、linux下打包Python3程序詳細方法

    windows、linux下打包Python3程序詳細方法

    這篇文章主要介紹了windows、linux下打包Python3程序詳細方法,需要的朋友可以參考下
    2020-03-03
  • Python+OpenCV圖像處理之直方圖統計

    Python+OpenCV圖像處理之直方圖統計

    直方圖就是對圖像的另外一種解釋,它描述了整幅圖像的灰度分布。通過直方圖我們可以對圖像的亮度、灰度分布、對比度等有了一個直觀的認識。本文將為大家詳細介紹一下如何通過OpenCV實現直方圖統計,感興趣的可以了解一下
    2021-12-12
  • python 通過SSHTunnelForwarder隧道連接redis的方法

    python 通過SSHTunnelForwarder隧道連接redis的方法

    今天小編就為大家分享一篇python 通過SSHTunnelForwarder隧道連接redis的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-02-02
  • Python批量添加水印的優(yōu)雅實現與進階

    Python批量添加水印的優(yōu)雅實現與進階

    在日常圖像處理中,為圖片添加水印是一項常見任務,有多種方法和工具可供選擇,本文將專注于使用Python語言結合PIL庫批量添加水印,感興趣的可以了解下
    2023-12-12
  • Python鍵盤輸入轉換為列表的實例

    Python鍵盤輸入轉換為列表的實例

    今天小編就為大家分享一篇Python鍵盤輸入轉換為列表的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Python 中的pygame安裝與配置教程詳解

    Python 中的pygame安裝與配置教程詳解

    這篇文章主要介紹了Python 中的pygame安裝與配置,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • Python繪圖系統之繪制散點圖,極坐標和子圖

    Python繪圖系統之繪制散點圖,極坐標和子圖

    這篇文章主要為大家詳細介紹了如何基于Python實現一個繪圖系統,可以支持繪制散點圖,極坐標和子圖,文中的示例代碼講解詳細,感興趣的可以了解下
    2023-09-09
  • 利用OpenCV中對圖像數據進行64F和8U轉換的方式

    利用OpenCV中對圖像數據進行64F和8U轉換的方式

    這篇文章主要介紹了利用OpenCV中對圖像數據進行64F和8U轉換的方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • Python實現類的創(chuàng)建與使用方法示例

    Python實現類的創(chuàng)建與使用方法示例

    這篇文章主要介紹了Python實現類的創(chuàng)建與使用方法,結合簡單計算器功能實例分析了Python類的定義與使用方法,需要的朋友可以參考下
    2017-07-07
  • python實現mask矩陣示例(根據列表所給元素)

    python實現mask矩陣示例(根據列表所給元素)

    這篇文章主要介紹了python實現mask矩陣示例(根據列表所給元素),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07

最新評論