Library / SDK
bterwijn/memory_graph avatar
bterwijn/memory_graph

memory_graph draws Python references as a graph you can inspect

Teaching tool and debugging aid in context of references, mutable data types, and shallow and deep copy.

1,096 stars81 forksPythonBSD-2-Clause

At a glance

What is it?
The memory_graph package renders the structure of Python data as a Graphviz graph, so aliasing, mutability and shallow versus deep copy become visible rather than something you have to infer from printed output. It is a teaching and debugging aid that requires Graphviz, and it is happiest on small data structures.
Who is it for?
Adopt memory_graph when you are teaching the Python data model, or when a shared-reference bug has defeated a print statement and you need to see which names point at the same value. Do not adopt it as a production debugger or profiler: it renders a graph per call, it depends on Graphviz being installed, and the project itself classifies the package as a beta aimed at education and debugging.
Can I use it commercially?
Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Installing the package and Graphviz itself

The package installs from PyPI with pip, and it needs Graphviz alongside it:

bash
pip install --upgrade memory_graph

The Graphviz dependency is the part people miss. The package metadata lists `graphviz` as its only runtime dependency, and the README states separately that Graphviz needs to be installed on the system as well. Python 3.7 or newer is required. The project version in the metadata is 0.3.87, and the classifiers call the package a beta whose intended audience is education and developers. The licence is BSD-2-Clause with the licence text in `LICENSE.txt`. Nothing is pinned in the pip command, so an upgrade can move the Graphviz binding under you, which is worth knowing if you script this into a teaching environment.

show opens a window, render writes a file

The two entry points differ in where the output goes, and the choice matters more than the API surface suggests. `mg.show` displays the graph on screen, which is what you want at a REPL or in a debugging session. `mg.render` writes to a file instead, and the README gives the accepted formats:

python
mg.render(data, "my_graph.pdf")
mg.render(data, "my_graph.svg")
mg.render(data, "my_graph.png")
mg.render(data, "my_graph.gv") # Graphviz DOT file
mg.render(data) # renders to default: 'memory_graph.pdf'

The file formats are the ones Graphviz documents, and the `.gv` option is the DOT source, which is the one to pick if you want to post-process the graph or feed it to something other than the Graphviz renderer. Calling `mg.render` with no filename produces `memory_graph.pdf`. A PDF is the default, which is a strange default for a screen tool, and worth overriding with the `.png` argument when you are working in a notebook.

Passing locals() is how the tool shows scope

The most useful call in the whole package is `mg.show(locals())`, because it draws every local variable in the current frame and, crucially, draws the sharing between them. The README's aliasing example is short enough to read in full:

python
a = [4, 3, 2]
b = a
b.append(1) # changing 'b' changes 'a'

print('a:', a)
print('b:', b)
print('ids:', id(a), id(b))
print('identical?:', a is b)

mg.show( locals() )

Printing the two lists tells you nothing, because both print `4, 3, 2, 1`. The README is explicit that the sharing cannot be verified by printing, only by comparing identity with `id()` or the `is` operator, and that this quickly becomes impractical for larger programs. A graph of `locals()` shows the aliasing directly, because the two names point at one node. The call stack visualization mentioned in the highlights extends the same idea to the complete program state.

The same diagram distinguishes mutable from immutable types

The tool earns its keep in teaching, because the same two-variable pattern produces visibly different graphs depending on the type. With a tuple, both names reference one immutable value, so rebinding `b` makes a copy and the two names end up pointing at separate values afterwards. With a list, the value is mutated in place and both names keep pointing at it. The README renders both states of the tuple case to show the transition:

python
import memory_graph as mg

a = (4, 3, 2)
b = a
mg.render(locals(), 'immutable1.png')

b += (1,)
mg.render(locals(), 'immutable2.png')

Two images, one before and one after the change, and the difference between them is the whole lesson. The README separates the types into immutable ones such as bool, int, float, complex, str, tuple, frozenset and bytes, and mutable ones such as list, set, dict and classes. The binary tree example in the highlights section and the sorting algorithm and sliding puzzle material in the topics list show the tool applied to structures large enough to be interesting.

Many data types are supported, including your own classes

The supported type list is broad, and the example builds a deliberately mixed structure to show it:

python
import memory_graph as mg

class My_Class:

    def __init__(self, x, y):
        self.x = x
        self.y = y

data = [ range(1, 2), (3, 4), {5, 6}, {7:'seven', 8:'eight'},  My_Class(9, 10) ]
mg.show(data)

A range, a tuple, a set, a dict and an instance of a user-defined class all sit in one list and are all rendered. That user classes are handled matters, because most of the aliasing bugs in real Python code involve objects with attributes rather than plain lists, and the attributes are what the graph has to walk to find the shared references. The README describes the tool as supporting many different data types, and the graph mirrors the data's hierarchy, which the author lists as one of the two main differences from Python Tutor.

How it differs from Python Tutor

The project states its inspiration openly, and also states the differences, which is more useful than a vague claim of novelty. Python Tutor is the browser-based snippet visualizer the README cites as its inspiration. The first difference is coverage: by running memory_graph locally, the author says it supports the features Python Tutor lists as unsupported, so it scales to full multi-file programs in many environments and IDEs rather than just snippets in a browser. The second difference is graph readability, where mirroring the data's hierarchy is claimed to help with larger graphs. The limitation that follows from both is that you need Python and Graphviz locally, and the rendering happens on your machine rather than in a browser, so a student without a local setup gets nothing. There is also a web version, the Memory Graph Web Debugger, which the README says runs a live demo with no installation required, and which can load a source file by URL and play it back.

Where the tool stops being the right choice

The limits are practical rather than documented, but they follow from the design. A graph is generated per call, so calling `mg.show` inside a loop or on every stack frame produces one rendering per event, and Graphviz output is not cheap to produce. The graph grows with the size of the reachable structure, and the README has a Graph Depth topic, which suggests depth is a knob rather than an unbounded default. The package is a beta, and it is classified under education and debuggers, so it is not a replacement for a real debugger with breakpoints and stepping. It draws a picture of the state; it does not stop execution, filter values, or let you mutate anything. For a production service where a large graph would be rendered on every request, a proper profiler or a targeted `id()` check is the better instrument. The tool is at its best on the small, confusing case where a picture settles the argument.

Editorial conclusion

Adopt memory_graph when you are teaching the Python data model, or when a shared-reference bug has defeated a print statement and you need to see which names point at the same value. Do not adopt it as a production debugger or profiler: it renders a graph per call, it depends on Graphviz being installed, and the project itself classifies the package as a beta aimed at education and debugging. Verify first that Graphviz is on the machine, since `mg.show` needs it, and decide early whether you want the on-screen window or the file output through `mg.render`, because the file path is the one that fits a test or a notebook.

Frequently asked questions

How do I install memory_graph?

Install it with `pip install --upgrade memory_graph`. Graphviz must be installed on the system as well, since the package renders through it, and the only runtime dependency listed in the package metadata is `graphviz`. Python 3.7 or newer is required.

What is the difference between mg.show and mg.render in memory_graph?

`mg.show` displays the graph on screen, while `mg.render` writes it to a file. `mg.render` accepts PDF, SVG, PNG and the Graphviz DOT format, and with no filename it renders to `memory_graph.pdf`.

How do I see which Python variables share the same value?

Call `mg.show(locals())` to draw a graph of every local variable in the frame, where shared references appear as one node reached by two names. The README notes that printing the lists cannot reveal this, and that comparing `id()` values or using `is` becomes impractical for larger programs.

What licence is memory_graph released under?

The package is released under the BSD-2-Clause licence, with the licence text in the LICENSE.txt file in the repository root and the licence identifier recorded in the package metadata.

Does memory_graph need an internet connection to work?

The package works locally through the pip install and the Graphviz dependency. There is also a Memory Graph Web Debugger that the README says runs a live demo with no installation required, and it can load a source file by URL.

Official sources

  1. bterwijn/memory_graph on GitHub
  2. Issues
  3. License: BSD-2-Clause
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bterwijn-memory-graph.svg)](https://hysenlabs.com/projects/bterwijn-memory-graph)

Was this useful?