17db96d56Sopenharmony_ci:mod:`multiprocessing.shared_memory` --- Shared memory for direct access across processes 27db96d56Sopenharmony_ci========================================================================================= 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci.. module:: multiprocessing.shared_memory 57db96d56Sopenharmony_ci :synopsis: Provides shared memory for direct access across processes. 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci**Source code:** :source:`Lib/multiprocessing/shared_memory.py` 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci.. versionadded:: 3.8 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ci.. index:: 127db96d56Sopenharmony_ci single: Shared Memory 137db96d56Sopenharmony_ci single: POSIX Shared Memory 147db96d56Sopenharmony_ci single: Named Shared Memory 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci-------------- 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ciThis module provides a class, :class:`SharedMemory`, for the allocation 197db96d56Sopenharmony_ciand management of shared memory to be accessed by one or more processes 207db96d56Sopenharmony_cion a multicore or symmetric multiprocessor (SMP) machine. To assist with 217db96d56Sopenharmony_cithe life-cycle management of shared memory especially across distinct 227db96d56Sopenharmony_ciprocesses, a :class:`~multiprocessing.managers.BaseManager` subclass, 237db96d56Sopenharmony_ci:class:`SharedMemoryManager`, is also provided in the 247db96d56Sopenharmony_ci``multiprocessing.managers`` module. 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ciIn this module, shared memory refers to "System V style" shared memory blocks 277db96d56Sopenharmony_ci(though is not necessarily implemented explicitly as such) and does not refer 287db96d56Sopenharmony_cito "distributed shared memory". This style of shared memory permits distinct 297db96d56Sopenharmony_ciprocesses to potentially read and write to a common (or shared) region of 307db96d56Sopenharmony_civolatile memory. Processes are conventionally limited to only have access to 317db96d56Sopenharmony_citheir own process memory space but shared memory permits the sharing 327db96d56Sopenharmony_ciof data between processes, avoiding the need to instead send messages between 337db96d56Sopenharmony_ciprocesses containing that data. Sharing data directly via memory can provide 347db96d56Sopenharmony_cisignificant performance benefits compared to sharing data via disk or socket 357db96d56Sopenharmony_cior other communications requiring the serialization/deserialization and 367db96d56Sopenharmony_cicopying of data. 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci.. class:: SharedMemory(name=None, create=False, size=0) 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci Creates a new shared memory block or attaches to an existing shared 427db96d56Sopenharmony_ci memory block. Each shared memory block is assigned a unique name. 437db96d56Sopenharmony_ci In this way, one process can create a shared memory block with a 447db96d56Sopenharmony_ci particular name and a different process can attach to that same shared 457db96d56Sopenharmony_ci memory block using that same name. 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci As a resource for sharing data across processes, shared memory blocks 487db96d56Sopenharmony_ci may outlive the original process that created them. When one process 497db96d56Sopenharmony_ci no longer needs access to a shared memory block that might still be 507db96d56Sopenharmony_ci needed by other processes, the :meth:`close()` method should be called. 517db96d56Sopenharmony_ci When a shared memory block is no longer needed by any process, the 527db96d56Sopenharmony_ci :meth:`unlink()` method should be called to ensure proper cleanup. 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci *name* is the unique name for the requested shared memory, specified as 557db96d56Sopenharmony_ci a string. When creating a new shared memory block, if ``None`` (the 567db96d56Sopenharmony_ci default) is supplied for the name, a novel name will be generated. 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci *create* controls whether a new shared memory block is created (``True``) 597db96d56Sopenharmony_ci or an existing shared memory block is attached (``False``). 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_ci *size* specifies the requested number of bytes when creating a new shared 627db96d56Sopenharmony_ci memory block. Because some platforms choose to allocate chunks of memory 637db96d56Sopenharmony_ci based upon that platform's memory page size, the exact size of the shared 647db96d56Sopenharmony_ci memory block may be larger or equal to the size requested. When attaching 657db96d56Sopenharmony_ci to an existing shared memory block, the ``size`` parameter is ignored. 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci .. method:: close() 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci Closes access to the shared memory from this instance. In order to 707db96d56Sopenharmony_ci ensure proper cleanup of resources, all instances should call 717db96d56Sopenharmony_ci ``close()`` once the instance is no longer needed. Note that calling 727db96d56Sopenharmony_ci ``close()`` does not cause the shared memory block itself to be 737db96d56Sopenharmony_ci destroyed. 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci .. method:: unlink() 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci Requests that the underlying shared memory block be destroyed. In 787db96d56Sopenharmony_ci order to ensure proper cleanup of resources, ``unlink()`` should be 797db96d56Sopenharmony_ci called once (and only once) across all processes which have need 807db96d56Sopenharmony_ci for the shared memory block. After requesting its destruction, a 817db96d56Sopenharmony_ci shared memory block may or may not be immediately destroyed and 827db96d56Sopenharmony_ci this behavior may differ across platforms. Attempts to access data 837db96d56Sopenharmony_ci inside the shared memory block after ``unlink()`` has been called may 847db96d56Sopenharmony_ci result in memory access errors. Note: the last process relinquishing 857db96d56Sopenharmony_ci its hold on a shared memory block may call ``unlink()`` and 867db96d56Sopenharmony_ci :meth:`close()` in either order. 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ci .. attribute:: buf 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci A memoryview of contents of the shared memory block. 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci .. attribute:: name 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci Read-only access to the unique name of the shared memory block. 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci .. attribute:: size 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci Read-only access to size in bytes of the shared memory block. 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ciThe following example demonstrates low-level use of :class:`SharedMemory` 1027db96d56Sopenharmony_ciinstances:: 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ci >>> from multiprocessing import shared_memory 1057db96d56Sopenharmony_ci >>> shm_a = shared_memory.SharedMemory(create=True, size=10) 1067db96d56Sopenharmony_ci >>> type(shm_a.buf) 1077db96d56Sopenharmony_ci <class 'memoryview'> 1087db96d56Sopenharmony_ci >>> buffer = shm_a.buf 1097db96d56Sopenharmony_ci >>> len(buffer) 1107db96d56Sopenharmony_ci 10 1117db96d56Sopenharmony_ci >>> buffer[:4] = bytearray([22, 33, 44, 55]) # Modify multiple at once 1127db96d56Sopenharmony_ci >>> buffer[4] = 100 # Modify single byte at a time 1137db96d56Sopenharmony_ci >>> # Attach to an existing shared memory block 1147db96d56Sopenharmony_ci >>> shm_b = shared_memory.SharedMemory(shm_a.name) 1157db96d56Sopenharmony_ci >>> import array 1167db96d56Sopenharmony_ci >>> array.array('b', shm_b.buf[:5]) # Copy the data into a new array.array 1177db96d56Sopenharmony_ci array('b', [22, 33, 44, 55, 100]) 1187db96d56Sopenharmony_ci >>> shm_b.buf[:5] = b'howdy' # Modify via shm_b using bytes 1197db96d56Sopenharmony_ci >>> bytes(shm_a.buf[:5]) # Access via shm_a 1207db96d56Sopenharmony_ci b'howdy' 1217db96d56Sopenharmony_ci >>> shm_b.close() # Close each SharedMemory instance 1227db96d56Sopenharmony_ci >>> shm_a.close() 1237db96d56Sopenharmony_ci >>> shm_a.unlink() # Call unlink only once to release the shared memory 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ciThe following example demonstrates a practical use of the :class:`SharedMemory` 1287db96d56Sopenharmony_ciclass with `NumPy arrays <https://numpy.org/>`_, accessing the 1297db96d56Sopenharmony_cisame ``numpy.ndarray`` from two distinct Python shells: 1307db96d56Sopenharmony_ci 1317db96d56Sopenharmony_ci.. doctest:: 1327db96d56Sopenharmony_ci :options: +SKIP 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci >>> # In the first Python interactive shell 1357db96d56Sopenharmony_ci >>> import numpy as np 1367db96d56Sopenharmony_ci >>> a = np.array([1, 1, 2, 3, 5, 8]) # Start with an existing NumPy array 1377db96d56Sopenharmony_ci >>> from multiprocessing import shared_memory 1387db96d56Sopenharmony_ci >>> shm = shared_memory.SharedMemory(create=True, size=a.nbytes) 1397db96d56Sopenharmony_ci >>> # Now create a NumPy array backed by shared memory 1407db96d56Sopenharmony_ci >>> b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf) 1417db96d56Sopenharmony_ci >>> b[:] = a[:] # Copy the original data into shared memory 1427db96d56Sopenharmony_ci >>> b 1437db96d56Sopenharmony_ci array([1, 1, 2, 3, 5, 8]) 1447db96d56Sopenharmony_ci >>> type(b) 1457db96d56Sopenharmony_ci <class 'numpy.ndarray'> 1467db96d56Sopenharmony_ci >>> type(a) 1477db96d56Sopenharmony_ci <class 'numpy.ndarray'> 1487db96d56Sopenharmony_ci >>> shm.name # We did not specify a name so one was chosen for us 1497db96d56Sopenharmony_ci 'psm_21467_46075' 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ci >>> # In either the same shell or a new Python shell on the same machine 1527db96d56Sopenharmony_ci >>> import numpy as np 1537db96d56Sopenharmony_ci >>> from multiprocessing import shared_memory 1547db96d56Sopenharmony_ci >>> # Attach to the existing shared memory block 1557db96d56Sopenharmony_ci >>> existing_shm = shared_memory.SharedMemory(name='psm_21467_46075') 1567db96d56Sopenharmony_ci >>> # Note that a.shape is (6,) and a.dtype is np.int64 in this example 1577db96d56Sopenharmony_ci >>> c = np.ndarray((6,), dtype=np.int64, buffer=existing_shm.buf) 1587db96d56Sopenharmony_ci >>> c 1597db96d56Sopenharmony_ci array([1, 1, 2, 3, 5, 8]) 1607db96d56Sopenharmony_ci >>> c[-1] = 888 1617db96d56Sopenharmony_ci >>> c 1627db96d56Sopenharmony_ci array([ 1, 1, 2, 3, 5, 888]) 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ci >>> # Back in the first Python interactive shell, b reflects this change 1657db96d56Sopenharmony_ci >>> b 1667db96d56Sopenharmony_ci array([ 1, 1, 2, 3, 5, 888]) 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_ci >>> # Clean up from within the second Python shell 1697db96d56Sopenharmony_ci >>> del c # Unnecessary; merely emphasizing the array is no longer used 1707db96d56Sopenharmony_ci >>> existing_shm.close() 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci >>> # Clean up from within the first Python shell 1737db96d56Sopenharmony_ci >>> del b # Unnecessary; merely emphasizing the array is no longer used 1747db96d56Sopenharmony_ci >>> shm.close() 1757db96d56Sopenharmony_ci >>> shm.unlink() # Free and release the shared memory block at the very end 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci.. class:: SharedMemoryManager([address[, authkey]]) 1797db96d56Sopenharmony_ci :module: multiprocessing.managers 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci A subclass of :class:`~multiprocessing.managers.BaseManager` which can be 1827db96d56Sopenharmony_ci used for the management of shared memory blocks across processes. 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci A call to :meth:`~multiprocessing.managers.BaseManager.start` on a 1857db96d56Sopenharmony_ci :class:`SharedMemoryManager` instance causes a new process to be started. 1867db96d56Sopenharmony_ci This new process's sole purpose is to manage the life cycle 1877db96d56Sopenharmony_ci of all shared memory blocks created through it. To trigger the release 1887db96d56Sopenharmony_ci of all shared memory blocks managed by that process, call 1897db96d56Sopenharmony_ci :meth:`~multiprocessing.managers.BaseManager.shutdown()` on the instance. 1907db96d56Sopenharmony_ci This triggers a :meth:`SharedMemory.unlink()` call on all of the 1917db96d56Sopenharmony_ci :class:`SharedMemory` objects managed by that process and then 1927db96d56Sopenharmony_ci stops the process itself. By creating ``SharedMemory`` instances 1937db96d56Sopenharmony_ci through a ``SharedMemoryManager``, we avoid the need to manually track 1947db96d56Sopenharmony_ci and trigger the freeing of shared memory resources. 1957db96d56Sopenharmony_ci 1967db96d56Sopenharmony_ci This class provides methods for creating and returning :class:`SharedMemory` 1977db96d56Sopenharmony_ci instances and for creating a list-like object (:class:`ShareableList`) 1987db96d56Sopenharmony_ci backed by shared memory. 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci Refer to :class:`multiprocessing.managers.BaseManager` for a description 2017db96d56Sopenharmony_ci of the inherited *address* and *authkey* optional input arguments and how 2027db96d56Sopenharmony_ci they may be used to connect to an existing ``SharedMemoryManager`` service 2037db96d56Sopenharmony_ci from other processes. 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci .. method:: SharedMemory(size) 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ci Create and return a new :class:`SharedMemory` object with the 2087db96d56Sopenharmony_ci specified ``size`` in bytes. 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci .. method:: ShareableList(sequence) 2117db96d56Sopenharmony_ci 2127db96d56Sopenharmony_ci Create and return a new :class:`ShareableList` object, initialized 2137db96d56Sopenharmony_ci by the values from the input ``sequence``. 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci 2167db96d56Sopenharmony_ciThe following example demonstrates the basic mechanisms of a 2177db96d56Sopenharmony_ci:class:`SharedMemoryManager`: 2187db96d56Sopenharmony_ci 2197db96d56Sopenharmony_ci.. doctest:: 2207db96d56Sopenharmony_ci :options: +SKIP 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci >>> from multiprocessing.managers import SharedMemoryManager 2237db96d56Sopenharmony_ci >>> smm = SharedMemoryManager() 2247db96d56Sopenharmony_ci >>> smm.start() # Start the process that manages the shared memory blocks 2257db96d56Sopenharmony_ci >>> sl = smm.ShareableList(range(4)) 2267db96d56Sopenharmony_ci >>> sl 2277db96d56Sopenharmony_ci ShareableList([0, 1, 2, 3], name='psm_6572_7512') 2287db96d56Sopenharmony_ci >>> raw_shm = smm.SharedMemory(size=128) 2297db96d56Sopenharmony_ci >>> another_sl = smm.ShareableList('alpha') 2307db96d56Sopenharmony_ci >>> another_sl 2317db96d56Sopenharmony_ci ShareableList(['a', 'l', 'p', 'h', 'a'], name='psm_6572_12221') 2327db96d56Sopenharmony_ci >>> smm.shutdown() # Calls unlink() on sl, raw_shm, and another_sl 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ciThe following example depicts a potentially more convenient pattern for using 2357db96d56Sopenharmony_ci:class:`SharedMemoryManager` objects via the :keyword:`with` statement to 2367db96d56Sopenharmony_ciensure that all shared memory blocks are released after they are no longer 2377db96d56Sopenharmony_cineeded: 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci.. doctest:: 2407db96d56Sopenharmony_ci :options: +SKIP 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ci >>> with SharedMemoryManager() as smm: 2437db96d56Sopenharmony_ci ... sl = smm.ShareableList(range(2000)) 2447db96d56Sopenharmony_ci ... # Divide the work among two processes, storing partial results in sl 2457db96d56Sopenharmony_ci ... p1 = Process(target=do_work, args=(sl, 0, 1000)) 2467db96d56Sopenharmony_ci ... p2 = Process(target=do_work, args=(sl, 1000, 2000)) 2477db96d56Sopenharmony_ci ... p1.start() 2487db96d56Sopenharmony_ci ... p2.start() # A multiprocessing.Pool might be more efficient 2497db96d56Sopenharmony_ci ... p1.join() 2507db96d56Sopenharmony_ci ... p2.join() # Wait for all work to complete in both processes 2517db96d56Sopenharmony_ci ... total_result = sum(sl) # Consolidate the partial results now in sl 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ciWhen using a :class:`SharedMemoryManager` in a :keyword:`with` statement, the 2547db96d56Sopenharmony_cishared memory blocks created using that manager are all released when the 2557db96d56Sopenharmony_ci:keyword:`with` statement's code block finishes execution. 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci 2587db96d56Sopenharmony_ci.. class:: ShareableList(sequence=None, *, name=None) 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci Provides a mutable list-like object where all values stored within are 2617db96d56Sopenharmony_ci stored in a shared memory block. This constrains storable values to 2627db96d56Sopenharmony_ci only the ``int``, ``float``, ``bool``, ``str`` (less than 10M bytes each), 2637db96d56Sopenharmony_ci ``bytes`` (less than 10M bytes each), and ``None`` built-in data types. 2647db96d56Sopenharmony_ci It also notably differs from the built-in ``list`` type in that these 2657db96d56Sopenharmony_ci lists can not change their overall length (i.e. no append, insert, etc.) 2667db96d56Sopenharmony_ci and do not support the dynamic creation of new :class:`ShareableList` 2677db96d56Sopenharmony_ci instances via slicing. 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci *sequence* is used in populating a new ``ShareableList`` full of values. 2707db96d56Sopenharmony_ci Set to ``None`` to instead attach to an already existing 2717db96d56Sopenharmony_ci ``ShareableList`` by its unique shared memory name. 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci *name* is the unique name for the requested shared memory, as described 2747db96d56Sopenharmony_ci in the definition for :class:`SharedMemory`. When attaching to an 2757db96d56Sopenharmony_ci existing ``ShareableList``, specify its shared memory block's unique 2767db96d56Sopenharmony_ci name while leaving ``sequence`` set to ``None``. 2777db96d56Sopenharmony_ci 2787db96d56Sopenharmony_ci .. method:: count(value) 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci Returns the number of occurrences of ``value``. 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci .. method:: index(value) 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci Returns first index position of ``value``. Raises :exc:`ValueError` if 2857db96d56Sopenharmony_ci ``value`` is not present. 2867db96d56Sopenharmony_ci 2877db96d56Sopenharmony_ci .. attribute:: format 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci Read-only attribute containing the :mod:`struct` packing format used by 2907db96d56Sopenharmony_ci all currently stored values. 2917db96d56Sopenharmony_ci 2927db96d56Sopenharmony_ci .. attribute:: shm 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci The :class:`SharedMemory` instance where the values are stored. 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ciThe following example demonstrates basic use of a :class:`ShareableList` 2987db96d56Sopenharmony_ciinstance: 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci >>> from multiprocessing import shared_memory 3017db96d56Sopenharmony_ci >>> a = shared_memory.ShareableList(['howdy', b'HoWdY', -273.154, 100, None, True, 42]) 3027db96d56Sopenharmony_ci >>> [ type(entry) for entry in a ] 3037db96d56Sopenharmony_ci [<class 'str'>, <class 'bytes'>, <class 'float'>, <class 'int'>, <class 'NoneType'>, <class 'bool'>, <class 'int'>] 3047db96d56Sopenharmony_ci >>> a[2] 3057db96d56Sopenharmony_ci -273.154 3067db96d56Sopenharmony_ci >>> a[2] = -78.5 3077db96d56Sopenharmony_ci >>> a[2] 3087db96d56Sopenharmony_ci -78.5 3097db96d56Sopenharmony_ci >>> a[2] = 'dry ice' # Changing data types is supported as well 3107db96d56Sopenharmony_ci >>> a[2] 3117db96d56Sopenharmony_ci 'dry ice' 3127db96d56Sopenharmony_ci >>> a[2] = 'larger than previously allocated storage space' 3137db96d56Sopenharmony_ci Traceback (most recent call last): 3147db96d56Sopenharmony_ci ... 3157db96d56Sopenharmony_ci ValueError: exceeds available storage for existing str 3167db96d56Sopenharmony_ci >>> a[2] 3177db96d56Sopenharmony_ci 'dry ice' 3187db96d56Sopenharmony_ci >>> len(a) 3197db96d56Sopenharmony_ci 7 3207db96d56Sopenharmony_ci >>> a.index(42) 3217db96d56Sopenharmony_ci 6 3227db96d56Sopenharmony_ci >>> a.count(b'howdy') 3237db96d56Sopenharmony_ci 0 3247db96d56Sopenharmony_ci >>> a.count(b'HoWdY') 3257db96d56Sopenharmony_ci 1 3267db96d56Sopenharmony_ci >>> a.shm.close() 3277db96d56Sopenharmony_ci >>> a.shm.unlink() 3287db96d56Sopenharmony_ci >>> del a # Use of a ShareableList after call to unlink() is unsupported 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ciThe following example depicts how one, two, or many processes may access the 3317db96d56Sopenharmony_cisame :class:`ShareableList` by supplying the name of the shared memory block 3327db96d56Sopenharmony_cibehind it: 3337db96d56Sopenharmony_ci 3347db96d56Sopenharmony_ci >>> b = shared_memory.ShareableList(range(5)) # In a first process 3357db96d56Sopenharmony_ci >>> c = shared_memory.ShareableList(name=b.shm.name) # In a second process 3367db96d56Sopenharmony_ci >>> c 3377db96d56Sopenharmony_ci ShareableList([0, 1, 2, 3, 4], name='...') 3387db96d56Sopenharmony_ci >>> c[-1] = -999 3397db96d56Sopenharmony_ci >>> b[-1] 3407db96d56Sopenharmony_ci -999 3417db96d56Sopenharmony_ci >>> b.shm.close() 3427db96d56Sopenharmony_ci >>> c.shm.close() 3437db96d56Sopenharmony_ci >>> c.shm.unlink() 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ciThe following examples demonstrates that ``ShareableList`` 3467db96d56Sopenharmony_ci(and underlying ``SharedMemory``) objects 3477db96d56Sopenharmony_cican be pickled and unpickled if needed. 3487db96d56Sopenharmony_ciNote, that it will still be the same shared object. 3497db96d56Sopenharmony_ciThis happens, because the deserialized object has 3507db96d56Sopenharmony_cithe same unique name and is just attached to an existing 3517db96d56Sopenharmony_ciobject with the same name (if the object is still alive): 3527db96d56Sopenharmony_ci 3537db96d56Sopenharmony_ci >>> import pickle 3547db96d56Sopenharmony_ci >>> from multiprocessing import shared_memory 3557db96d56Sopenharmony_ci >>> sl = shared_memory.ShareableList(range(10)) 3567db96d56Sopenharmony_ci >>> list(sl) 3577db96d56Sopenharmony_ci [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci >>> deserialized_sl = pickle.loads(pickle.dumps(sl)) 3607db96d56Sopenharmony_ci >>> list(deserialized_sl) 3617db96d56Sopenharmony_ci [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci >>> sl[0] = -1 3647db96d56Sopenharmony_ci >>> deserialized_sl[1] = -2 3657db96d56Sopenharmony_ci >>> list(sl) 3667db96d56Sopenharmony_ci [-1, -2, 2, 3, 4, 5, 6, 7, 8, 9] 3677db96d56Sopenharmony_ci >>> list(deserialized_sl) 3687db96d56Sopenharmony_ci [-1, -2, 2, 3, 4, 5, 6, 7, 8, 9] 3697db96d56Sopenharmony_ci 3707db96d56Sopenharmony_ci >>> sl.shm.close() 3717db96d56Sopenharmony_ci >>> sl.shm.unlink() 372