繁体   English   中英

通过Python中的套接字在两个进程之间传递共享内存对象

[英]Passing shared memory object between two processes via socket in Python

我的应用程序包含两个通过TCP套接字连接的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()

我的问题归结为:如何通过套接字传递有关第二个进程要访问的内存段的信息? 我已经尝试了以下方法(同时使用pickledill ),但都无济于事:

  • 直接在文件上使用mmap.mmap或存储其内容。 结果: TypeError: Required argument 'fileno' (pos 1) not found在服务器端拆箱时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在客户端进行腌制时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传递,当然(据说)可以解决所有问题。

回答我的问题,因为我想, 究竟我是这样做。 根据man mmap说法, 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有一个单独的部分称为“ ERRORS”

至于共享内存,有posix_ipcsysv_ipc模块(后者支持更广泛的OS)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM