Die Python-Funktion memoryview(obj) erzeugt einen Zero-Copy-View auf ein Buffer-Objekt — bytes, bytearray, array.array oder numpy-Arrays. Slicing eines memoryview erzeugt KEINE Kopie der Daten, sondern nur einen neuen View. In Performance-kritischen I/O- und Binär-Daten-Operationen kann das gewaltige Speicher- und CPU-Ersparnis bedeuten.

Einleitung

Wer in Python mit bytes arbeitet und immer wieder neue Slices erzeugt, kopiert ständig Daten. Bei Multi-MB-Buffern wird das schnell teuer. memoryview umgeht das, indem es auf den vorhandenen Speicher zeigt, ohne ihn zu kopieren.

Anwendungsfälle:

  • Streaming-I/O: Daten aus einer Datei oder einem Socket in einen großen Buffer lesen und Sub-Ranges per memoryview an Verarbeitungsfunktionen weiterreichen.
  • Binär-Protokolle: Header-Bytes lesen, Payload als View weitergeben — ohne Kopie.
  • NumPy-Interop: memoryview ist die universelle „Lingua Franca" zwischen Buffer-Konsumenten.

Mit cast() lässt sich der View typisiert umschalten — von Bytes auf Floats, Doubles, Ints etc.

Syntax

Python Syntax
memoryview(buffer_object)
Parameter
buffer_object

Ein Objekt, das das Buffer-Protokoll unterstützt: bytes, bytearray, array.array, mmap.mmap, numpy.ndarray.

Rückgabewert

Eine memoryview-Instanz mit Attributen format, itemsize, nbytes, ndim, shape, strides, readonly.

Beispiele

Zero-Copy-View

Der grundlegende Effekt: Slicing erzeugt keine Kopie der Daten, sondern nur einen anderen View:

Python Beispiel
data = bytearray(b"abcdef")
view = memoryview(data)
sub = view[1:4]
print(bytes(sub))
# Modifikation des Original wirkt auch in den Views:
data[1] = ord('B')
print(bytes(sub))
Output
b'bcd'
b'Bcd'

View ist read/write je nach Quelle

Bei bytes ist der View read-only, bei bytearray schreibbar:

Python Beispiel
v_ro = memoryview(b"hello")
print(v_ro.readonly)
v_rw = memoryview(bytearray(b"hello"))
print(v_rw.readonly)
v_rw[0] = ord('H')
print(bytes(v_rw))
Output
True
False
b'Hello'

cast() — typisierten View bauen

Mit cast() lassen sich Bytes als Sequenz von Ints, Floats oder Doubles betrachten — ohne die Daten zu kopieren:

Python Beispiel
import struct
# Drei Doubles als Bytes packen:
raw = struct.pack("3d", 1.5, 2.5, 3.5)
view = memoryview(raw).cast("d")
print(list(view))
Output
[1.5, 2.5, 3.5]

Praktische Beispiele

Großen Datei-Buffer streamen ohne Kopie

readinto() füllt einen vorab allokierten Buffer — memoryview reicht Sub-Ranges weiter, ohne neue Bytes-Kopien zu produzieren:

Python Beispiel
BUF_SIZE = 4096
buf = bytearray(BUF_SIZE)
view = memoryview(buf)

with open("big.bin", "rb") as f:
    while True:
        n = f.readinto(buf)
        if not n:
            break
        process(view[:n])   # zero-copy

Header und Payload trennen

Beim Parsen binärer Protokolle (TCP, Image-Formate) lässt sich der Header lesen und die Payload als View weitergeben:

Python Beispiel
packet = bytearray(b"\x00\x10HELLO PAYLOAD")
view = memoryview(packet)
header = view[:2]                           # zwei Header-Bytes
payload = view[2:]                          # Rest als View
print(int.from_bytes(header, "big"), bytes(payload))
Output
16 b'HELLO PAYLOAD'

Performance-Vergleich

Bei großen Buffern macht memoryview einen massiven Unterschied — Slicing produziert sonst Kopien:

Python Beispiel
from time import perf_counter

big = bytes(10_000_000)

# Mit Kopien:
t = perf_counter()
for _ in range(100):
    sub = big[1000:2000]
copy_time = perf_counter() - t

# Mit memoryview:
t = perf_counter()
view = memoryview(big)
for _ in range(100):
    sub = view[1000:2000]
view_time = perf_counter() - t

print(f"copies: {copy_time*1000:.2f} ms, views: {view_time*1000:.2f} ms")
Output
copies: ... ms, views: ... ms (deutlich schneller)

Praktische Hinweise

  • Zero-Copy-Slicing ist der Hauptvorteil — wer nicht-trivialen Slice-Workload hat, gewinnt enorm.
  • Lebenszeit beachten: Solange ein memoryview existiert, kann das Original nicht resized werden (bytearray.append schlägt fehl).
  • cast() für typisierte Views — Buffer als Floats, Doubles, Ints betrachten.
  • release() schließt einen View explizit — wichtig bei langlebigen Buffern.
  • Verwandte Typen: bytes, bytearray, array.array, mmap, numpy.ndarray.
/ Weiter

Zurück zu Builtin Functions

Zur Übersicht