2016-12-04 60 views
2

我的應用程序由兩個通過TCP套接字連接的Python進程組成。第一個過程用於讀取文件並將它們放在共享內存中,而不是按下套接字,以便其他進程可以讀取它們。通過Python中的套接字在兩個進程之間傳遞共享內存對象

import os 
import zmq 
import mmap 
import time 
import ctypes 
import pickle 
import dill 
import tempfile 
import multiprocessing as mp 

MEETING_POINT = 'tcp://127.0.0.1:12345' 
FILEFD, FILEPATH = tempfile.mkstemp() 


def run_server(): 
    Server().run() 


def read_file(): 
    return open(FILEPATH, 'r').read() 


class Client(object): 
    def __init__(self): 
     self.ctx = zmq.Context() 
     self.socket = self.ctx.socket(zmq.DEALER) 
     self.socket.connect(MEETING_POINT) 

    def cleanup(self): 
     self.socket.close() 
     self.ctx.term() 

    def run(self): 
     self.socket.send(dill.dumps(read_file())) 


class Server(object): 
    def __init__(self): 
     self.ctx = zmq.Context() 
     self.socket = self.ctx.socket(zmq.DEALER) 
     self.socket.bind(MEETING_POINT) 

    def cleanup(self): 
     self.socket.close() 
     self.ctx.term() 

    def run(self): 
     f = dill.loads(self.socket.recv()) 
     print(f) 


def main(): 
    with open(FILEPATH, 'w') as fd: 
     fd.write('blah') 

    mp.Process(target=run_server).start() 
    time.sleep(.5) # a (poor, but tolerable) alternative to handshaking 
    Client().run() 


if __name__ == '__main__': 
    main() 

我的問題歸結爲:我怎麼通過左右的內存段的信息,第二過程是接入,通過插座?直接

  • 使用mmap.mmap上的文件或存儲它的內容:我已經試過以下(既pickledill),都無濟於事。結果:TypeError: Required argument 'fileno' (pos 1) not found當在服務器端取消時。

  • 使用multiprocessing.Array:

    with open(FILEPATH, 'r') as fd: contents = bytearray(fd.read()) arr = mp.Array(ctypes.c_byte, contents, lock=False)

結果:pickle.PicklingError: Can't pickle <class 'multiprocessing.sharedctypes.c_byte_Array_4'>: it's not found as multiprocessing.sharedctypes.c_byte_Array_4在客戶端酸洗時。

我相信有一個更簡單的(和工作)的方式來做到這一點,是嗎?我無法預先讀取所有必需的文件,並將它們打包到multiprocessing.Array中,以在創建服務器進程時作爲args傳遞,當然這將會(據推測)解決所有問題。

回答

0

回答我自己的問題,因爲我想明白究竟是我該怎麼做。根據man mmap,對於第二個進程能夠讀取第一個內存的情況,創建一個帶有MAP_SHARED標誌的內存段就足夠了。因此,在mmap.mmap的構造這個標誌是默認設置,都是一個需要做的就是通過文件名,而不是一個類的實例:

# sometime during the first process' execution 
fd = open(filepath_to_process, 'w') 
memory = mmap.mmap(fd.fileno(), 0) 
socket.send(filepath_to_process) 

# on the other side of socket, this happens: 
unprocessed_filepath = socket.recv() 
fresh_fd = open(unprocessed_filepath, 'r') 
mm = mmap.mmap(fresh_fd.fileno(), 0) 

# voilà! All the changes are now propagated to the second process 

當然,訪問模式的文件和存儲區必須匹配,但在man mmap中有一個單獨的部分,稱爲「錯誤」

至於共享內存,有posix_ipcsysv_ipc模塊(後者支持更多種類的操作系統)。

相關問題