使用 Python 3.x < 3.8 访问 'shared memory'

Accessing 'shared memory' with Python 3.x < 3.8

在我的应用程序中,多个进程依赖于一个来源,相机或视频流。与 Python 3.8 一起引入的 'Shared memory' 提供了一种巧妙的解决方案,因为一个进程在专用地址上共享帧,而任何其他进程都可以拾取它。不幸的是,一个进程依赖于 Python 3.8.

中不可用的库

是否可以通过确定地址的标识符得到Python 3.x<3.8的'shared memory'?

欢迎提出任何建议!

您可以使用mmap并在进程之间共享内存映射文件。

您可以按照 this blog post 作为指导。

@Joac 为我指明了正确的方向,我对共享内存、mmap 以及 shmgetshmat 等有了更多的了解。有兴趣了解更多相关信息 我发现以下视频和博客-post 特别有用:

How to Map Files into Memory in C (mmap, memory mapped file io)

How to Set up Shared Memory in Your Linux and MacOS Programs. (shmget, shmat, shmdt, shmctl, ftok)

Using python to read shared memory under Linux

最后,我通过为 Python2.x 引入的 posix_ipc 模块解决了这个问题,实际上它与本机 Python3.8 解决方案非常相似我指的是上面。

从 Python 3.8 脚本共享视频并使用适用于 Python 3.x < Python 3.8 的脚本处理视频的示例代码。请随时对此示例片段发表评论。我相信有可以改进的元素:

from multiprocessing import shared_memory

import cv2
import numpy as np

if __name__ == "__main__":
    video_path = "/home/john/Videos/sample.mp4"
    video_capture = cv2.VideoCapture(video_path)
    fps = video_capture.get(cv2.CAP_PROP_FPS)

    return_value, frame = video_capture.read()
    
    shm = shared_memory.SharedMemory(name="video_stream", create=True, size=frame.nbytes)

    shared_image = np.ndarray(frame.shape, dtype=frame.dtype, buffer=shm.buf)
    shared_image[:] = frame[:]

    while True:
        return_value, frame = video_capture.read()
        shared_image[:] = frame[:]

        if (return_value):
            cv2.imshow('python3.8', shared_image)

        delay = int((1/fps) * 1000)
        if (cv2.waitKey(delay) & 0xFF == ord('q')):
            break

    video_capture.release()
    cv2.destroyAllWindows()
import mmap

import cv2
import numpy as np
import posix_ipc

if __name__ == "__main__":
    shm = posix_ipc.SharedMemory('/video_stream')
    mapfile = mmap.mmap(shm.fd, shm.size)

    shared_image = np.ndarray((720, 1280, 3), dtype=np.uint8,
                              buffer=mapfile.read())

    while True:
        mapfile.seek(0)
        shared_image = np.ndarray((720, 1280, 3), dtype=np.uint8,
                                  buffer=mapfile.read())
        cv2.imshow('python3.6', shared_image)

        if (cv2.waitKey(1) & 0xFF == ord('q')):
            break

    cv2.destroyAllWindows()