Skip to main content

Draw a graph of your data to see the structure of its references.

Project description

Graph your Memory

Want to draw a graph of your data in Python to better understand its structure or the Python memory model in general?

Just call memory_graph.show(your_data), an example:

data = [ (1, 2), [3, 4], {5:'five', 6:'six'} ]

import memory_graph
memory_graph.show( data, block=True )

This shows the graph with the starting point of your 'data' drawn using thick lines, the program blocks until the ENTER key is pressed.

image

If show() doesn't work well on your system (the PDF viewer integration is platform specific) use render() to output the graph in the format of your choosing and open it yourself.

memory_graph.render( data, "my_graph.png", block=True )

Graph all Local Variables

Often it is useful to graph all the local variables using:

memory_graph.show( locals(), block=True )

Also useful to set as 'watch' in a debugger tool:

memory_graph.render( locals(), "my_debug_graph.pdf" )

Larger Example

This larger example shows objects that share a class (static) variable and also shows we can handle recursive references although the graph layout might be less pretty (trust me there are good reasons for this).

my_list = [10, 20, 10]

class My_Class:
    my_class_var = 20 # class variable: shared by different objects
    
    def __init__(self):
        self.var1 = "foo"
        self.var2 = "bar"
        self.var3 = 20

obj1 = My_Class()
obj2 = My_Class()

data=[my_list, my_list, obj1, obj2]

my_list.append(data) # recursive reference

import memory_graph
memory_graph.show( locals() )

image

Config

Different aspects of memory_graph can be configured.

Config Visualization, graphviz_nodes

Configure how the nodes of the graph are visualized with:

  • memory_graph.graphviz_nodes.linear_layout_vertical : bool
    • if False, linear node layout is horizontal
  • memory_graph.graphviz_nodes.linear_any_ref_layout_vertical : bool
    • if False, linear node layout is horizontal if it has any references
  • memory_graph.graphviz_nodes.linear_any_ref_layout_vertical : bool
    • if False, linear node layout is horizontal if it has all references
  • memory_graph.graphviz_nodes.key_value_layout_vertical : bool
    • if False, key_value node layout is horizontal
  • memory_graph.graphviz_nodes.key_value_any_ref_layout_vertical : bool
    • if False, key_value node layout is horizontal if it has any references
  • memory_graph.graphviz_nodes.key_value_any_ref_layout_vertical : bool
    • if False, key_value node layout is horizontal if it has all references
  • memory_graph.graphviz_nodes.padding : int
    • the padding in nodes
  • memory_graph.graphviz_nodes.padding : int
    • the spacing in nodes
  • memory_graph.graphviz_nodes.join_references_count : int
    • minimum number of reference we join together
  • memory_graph.graphviz_nodes.join_circle_size : string
    • size of the join circle
  • memory_graph.graphviz_nodes.join_circle_minlen : string
    • extra space for references above a join circle
  • memory_graph.graphviz_nodes.max_string_length : int
    • maximum string length where the string is cut off
  • memory_graph.graphviz_nodes.category_to_color_map : dict
    • mapping van type/caterogries to node colors
  • memory_graph.graphviz_nodes.uncategorized_color : dict
    • color for unkown types/categories
  • memory_graph.graphviz_nodes.graph_attr : dict
  • memory_graph.graphviz_nodes.node_attr : dict
  • memory_graph.graphviz_nodes.edge_attr : dict

See for color names: graphviz colors

To configure more about the visualization use:

digraph = memory_graph.create_graph( locals() )

and see the graphviz api to render it in many different ways.

Config Graph Structure, rewrite_to_node

Configure the structure of the nodes in the graph with:

  • memory_graph.rewrite_to_node.reduce_reference_parents : set
    • the node types/categories for which we remove the reference to children
  • memory_graph.rewrite_to_node.reduce_reference_children : bool
    • the node types/categories for which we remove the reference from parents

Config Node Creation, rewrite

Configure what nodes are created based on reading the given data structure:

  • memory_graph.rewrite.ignore_types : dict
    • all types that we ignore, these will not be in the graph
  • memory_graph.rewrite.singular_types : set
    • all types rewritten to node as singular values (bool, int, float, ...)
  • memory_graph.rewrite.linear_types : set
    • all types rewritten to node as linear values (tuple, list, set, ...)
  • memory_graph.rewrite.dict_types : set
    • all types rewritten to node as dictionary values (dict, mappingproxy)
  • memory_graph.rewrite.dict_ignore_dunder_keys : bool
    • determines if we ignore dunder keys ('__example') in dict_types
  • memory_graph.rewrite.custom_accessor_functions : dict
    • custom accessor functions to defined how to read various types

Config Examples

With configuration:

memory_graph.graphviz_nodes.layout_vertical = False                       # draw lists,tuples,sets,... horizontally
memory_graph.graphviz_nodes.type_category_to_color_map['list'] = 'yellow' # change color of 'list' type
memory_graph.graphviz_nodes.spacing=15                                    # more spacing in each node
memory_graph.graphviz_nodes.graph_attr['ranksep']='1.2'                   # more vertical separation
memory_graph.graphviz_nodes.graph_attr['nodesep']='1.2'                   # more horizontal separation
memory_graph.rewrite_to_node.reduce_reference_types.remove(int)           # draw references to 'int' type

the last example looks like:

image

Custom Accessor Functions

For any type a custom accessor function can be introduced. For example Panda DataFrames and Series are not visualized correctly by default. This can be fixed by adding custom accessor functions:

import pandas as pd

data = {'Name':['Tom', 'Anna', 'Steve', 'Lisa'],
        'Age':[28,34,29,42],
        'Length':[1.70,1.66,1.82,1.73] }
df = pd.DataFrame(data)

import memory_graph
memory_graph.rewrite.custom_accessor_functions[pd.DataFrame] = lambda d: list(d.iteritems())
memory_graph.rewrite.custom_accessor_functions[pd.Series] = lambda d: list(d.items())
memory_graph.rewrite_to_node.reduce_reference_parents.add("DataFrame")
memory_graph.rewrite_to_node.reduce_reference_parents.add("Series")
memory_graph.graphviz_nodes.category_to_color_map['Series'] = 'lightskyblue'
memory_graph.show( locals() )

which results in:

image

Troubleshooting

When edges overlap it can be hard to distinguish them. Using an interactive graphviz viewer, such as xdot, on a '*.gv' output file will help.

Install

Install using pip:

pip install memory-graph

Additionally Graphviz needs to be installed.

Author

Bas Terwijn

Inspiration

Inspired by PythonTutor.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

memory_graph-0.1.14.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

memory_graph-0.1.14-py2.py3-none-any.whl (11.7 kB view details)

Uploaded Python 2Python 3

File details

Details for the file memory_graph-0.1.14.tar.gz.

File metadata

  • Download URL: memory_graph-0.1.14.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/4.6.4 keyring/23.5.0 pkginfo/1.8.2 readme-renderer/34.0 requests-toolbelt/0.9.1 requests/2.25.1 rfc3986/1.5.0 tqdm/4.57.0 urllib3/1.26.5 CPython/3.10.6

File hashes

Hashes for memory_graph-0.1.14.tar.gz
Algorithm Hash digest
SHA256 5ff26e29761e4aac7697939970b24f3313e213af5938c4e34356dbf957d6b25b
MD5 e02c374cf037cd04262e0f8858d65d10
BLAKE2b-256 384d2f11a207f38b852e253461715c786303011dcf05d665450a4d13c6e64e19

See more details on using hashes here.

File details

Details for the file memory_graph-0.1.14-py2.py3-none-any.whl.

File metadata

  • Download URL: memory_graph-0.1.14-py2.py3-none-any.whl
  • Upload date:
  • Size: 11.7 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/4.6.4 keyring/23.5.0 pkginfo/1.8.2 readme-renderer/34.0 requests-toolbelt/0.9.1 requests/2.25.1 rfc3986/1.5.0 tqdm/4.57.0 urllib3/1.26.5 CPython/3.10.6

File hashes

Hashes for memory_graph-0.1.14-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 daa29c0a83981e7cd2ba7587904ac5984fc9343ea57b6b7faa926d0247c131dc
MD5 3f28ac8c939807d19ae393fff6b82a0b
BLAKE2b-256 915c18aae181c6d87692e5a85d865c5596bb5dbd7a582c0733fb3a449b5ab673

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page