memoryview.release()
An open view LOCKS its buffer against resizing. release is how you let go early, rather than waiting for garbage collection to do it.
Common call
view.release()
Returns
None — the view becomes unusable
Replaces
del view, which only works if nothing else refers to it
Watch out
a live view makes bytearray.append raise BufferError
memoryview.release()
→ None
Examples
1. Releases the lock
b = bytearray(b'abc')
m = memoryview(b)
m.release()
b.append(100)
Returns
bytearray(b'abcd')2. Without release
b = bytearray(b'abc')
m = memoryview(b)
b.append(100)
Returns
BufferError: Existing exports of data: object cannot be re-sized3. View is dead after
m.release()
m.tolist()
Returns
ValueError: operation forbidden on released memoryview object4. Releasing twice is fine
m.release()
m.release()
Returns
None5. Context manager
with memoryview(b'xy') as v:
print(len(v))
Returns
2, then released automatically6. Returns None
memoryview(b'abc').release()
Returns
NonePitfalls
1. A live view blocks resizing
This is the problem release exists to solve. While any view is open, the bytearray behind it cannot grow or shrink, and append raises BufferError rather than waiting.
Blocked
b = bytearray(b'abc') m = memoryview(b) b.append(100)
BufferError: Existing exports of data: object cannot be re-sized
Release first
m.release() b.append(100)
works
2. Every operation fails afterwards
The view is not merely detached, it is unusable. Reading, slicing or even calling len raises ValueError, so a released view must not be kept around and used later.
Dead view
m.release() len(m)
ValueError: operation forbidden on released memoryview object
Release last
data = m.tobytes() m.release()
copy taken before releasing
3. Slices of a view are separate exports
Releasing the parent does not release views you sliced from it. Every one holds its own lock on the buffer, so all of them must go before it can be resized.
Child still holds it
m = memoryview(b) s = m[:2] m.release() b.append(1)
BufferError — s is still open
Release both
s.release() m.release() b.append(1)
works
4. Not needed for immutable sources
A view over bytes locks nothing meaningful, because bytes cannot be resized anyway. release is only worth reaching for with bytearray, array or mmap.
Pointless ceremony
m = memoryview(b'abc') m.release()
no lock was ever a problem
Let it be collected
m = memoryview(b'abc')
nothing to manage
When to use
Use it
- Freeing a bytearray, array or mmap for resizing before the view goes out of scope
- Deterministic cleanup rather than relying on garbage collection
- Long-lived buffers where holding an export would block later growth
Reach for something else
- Views over immutable bytes, which lock nothing that matters
- Short-lived views — a with block does this for you
- After taking the copy you needed → the view is disposable anyway
Notes
Complexity
O(1) — releases the buffer export
Return
Always None; calling it again is harmless
CPython impl
Objects/memoryobject.c :: memory_release
Memory
Drops the reference keeping the source buffer pinned
Thread-safe
Releasing while another thread reads the view raises there
FAQ
Because an open memoryview is an "export" of that buffer, and resizing could move the memory the view points at. Python refuses rather than leaving a dangling view — release the view and the append succeeds.
m.release() b.append(100)
History
3.2
release added, along with memoryview support for the with statement.