Skip to content

Instantly share code, notes, and snippets.

@deeplook
Last active December 12, 2015 06:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save deeplook/4731035 to your computer and use it in GitHub Desktop.
Save deeplook/4731035 to your computer and use it in GitHub Desktop.
An experimental extension for an IPython magic command to show object graphs.
"""
An experimental extension for an IPython magic command to show object graphs.
Strongly based on tkf's code for the extension itself
and mine for turning a Python namespace into a GraphViz DOT source:
- https://github.com/tkf/ipython-hierarchymagic
- http://pypi.python.org/pypi/pyrels/0.1.1
Read respective copyrights there!
Dinu Gherman
2013-02-12
"""
from IPython.core.magic \
import Magics, magics_class, line_magic, cell_magic
from IPython.core.magic_arguments \
import argument, magic_arguments, parse_argstring
from IPython.core.display import display_png, display_svg
from pyrels.pyrels2dot import namespace2dot_str
def run_dot(code, options=[], format='png'):
# mostly copied from sphinx.ext.graphviz.render_dot
import os
from subprocess import Popen, PIPE
from sphinx.util.osutil import EPIPE, EINVAL
dot_args = ['dot'] + options + ['-T', format]
if os.name == 'nt':
# Avoid opening shell window.
# * https://github.com/tkf/ipython-hierarchymagic/issues/1
# * http://stackoverflow.com/a/2935727/727827
p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE,
creationflags=0x08000000)
else:
p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
wentwrong = False
try:
# Graphviz may close standard input when an error occurs,
# resulting in a broken pipe on communicate()
stdout, stderr = p.communicate(code)
except (OSError, IOError), err:
if err.errno != EPIPE:
raise
wentwrong = True
except IOError, err:
if err.errno != EINVAL:
raise
wentwrong = True
if wentwrong:
# in this case, read the standard output and standard error streams
# directly, to get the error message(s)
stdout, stderr = p.stdout.read(), p.stderr.read()
p.wait()
if p.returncode != 0:
raise RuntimeError('dot exited with error:\n[stderr]\n{0}'
.format(stderr))
return stdout
@magics_class
class GraphvizMagic(Magics):
@magic_arguments()
@argument(
'-f', '--format', default='png', choices=('png', 'svg'),
help='output format (png/svg)'
)
@argument(
'options', default=[], nargs='*',
help='options passed to the `dot` command'
)
@cell_magic
def objgraph(self, line, cell):
"""Draw a figure using Graphviz dot command."""
args = parse_argstring(self.objgraph, line)
dot = namespace2dot_str(eval(cell, _ip_globals))
image = run_dot(dot, args.options, format=args.format)
if args.format == 'png':
display_png(image, raw=True)
elif args.format == 'svg':
display_svg(image, raw=True)
def load_ipython_extension(ip):
"""Load the extension in IPython."""
global _loaded
global _ip_globals
if not _loaded:
ip.register_magics(GraphvizMagic)
_ip_globals = ip.user_global_ns
_loaded = True
else:
_ip_globals = ip.user_global_ns
_loaded = False
@masonlouie
Copy link

There appears to be a bug in objgraph where when I run:
%%objgraph -f svg
{"myInt": n, "myList": L}
from the notebook tutorial
http://nbviewer.ipython.org/gist/deeplook/4770302
I get an error saying "n" is not defined. (ipy debug trace at the end of this comment).

Looking inside of objgraph(), I see that the scope eval() is being run in doesn't have any of the local variables. I tried putting in @needs_local_scope and adding a scope parameter like in rmagic, but that didn't work. :-(

ameError Traceback (most recent call last)
in ()
----> 1 get_ipython().run_cell_magic(u'objgraph', u'-f svg ', u'{"myInt": n, "myList": L}')

/usr/local/lib/python2.7/dist-packages/IPython/core/interactiveshell.pyc in run_cell_magic(self, magic_name, line, cell)
2120 magic_arg_s = self.var_expand(line, stack_depth)
2121 with self.builtin_trap:
-> 2122 result = fn(magic_arg_s, cell)
2123 return result
2124

/home/mason/.config/ipython/extensions/ipython_object_graphs.py in objgraph(self, line, cell, foo)

/usr/local/lib/python2.7/dist-packages/IPython/core/magic.pyc in (f, _a, *_k)
189 # but it's overkill for just that one bit of state.
190 def magic_deco(arg):
--> 191 call = lambda f, _a, *_k: f(_a, *_k)
192
193 if callable(arg):

/home/mason/.config/ipython/extensions/ipython_object_graphs.py in objgraph(self, line, cell, foo)
84 else: foo = globals()
85
---> 86 cell = namespace2dot_str(eval(cell, foo))
87 image = run_dot(cell, args.options, format=args.format)
88

/home/mason/.config/ipython/extensions/ipython_object_graphs.py in ()

NameError: name 'n' is not defined

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment