Skip to content
Python Basics: Expose a Read-Only Mapping View

Python Basics: Expose a Read-Only Mapping View

October 27, 2026

An API can expose configuration keys for reading without allowing callers to assign through that mapping. MappingProxyType provides a live read-only view. It does not freeze the original dictionary or the objects stored inside it.

Prepare a scratch directory

Tested on Linux with CPython 3.12.14. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. Run Python without -O so the assertions remain enabled. Any generated fixture files live inside an automatically cleaned temporary directory.

Keep using the same terminal. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-mapping-proxy.py:

from types import MappingProxyType

settings = {"mode": "preview", "labels": ["draft"]}
view = MappingProxyType(settings)
assert view["mode"] == "preview"
try:
    view["mode"] = "ready"
except TypeError:
    print("Assignment through view: blocked")
else:
    raise AssertionError("View allowed assignment")

snapshot = dict(view)
settings["mode"] = "ready"
assert view["mode"] == "ready"
assert snapshot["mode"] == "preview"
print("Live mode:", view["mode"])
print("Copied mode:", snapshot["mode"])

view["labels"].append("review")
assert settings["labels"] == ["draft", "review"]
assert snapshot["labels"] is settings["labels"]
print("Nested list remains mutable:", settings["labels"])

Run it:

python3 -B demonstrate-mapping-proxy.py

Observed output:

Assignment through view: blocked
Live mode: ready
Copied mode: preview
Nested list remains mutable: ['draft', 'review']

Read the result

The proxy blocks item assignment through its own interface. The owner can still update the underlying dictionary, and the view reflects that update immediately. dict(view) copies the mapping entries, so its scalar mode value stays unchanged. Both mappings still refer to the same nested list, which makes the shallow-copy boundary visible.

Apply it carefully

A mapping proxy is an access-interface choice, not a deep immutability or synchronization mechanism. Use immutable nested values when callers must not mutate them, and choose an explicit snapshot strategy when later owner changes should not be visible. A shallow dictionary copy is enough only when sharing the values is acceptable. Concurrent mutation can also affect iteration; a read-only view does not make a changing dictionary thread-safe.

The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.

Clean up

Remove the source and then the empty practice directory:

rm -- demonstrate-mapping-proxy.py
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect the remaining files rather than deleting unknown contents.

Acknowledgements

This post was created with assistance from AI.

Last updated on