2

In my question about tracking the python execution I was recommended to use pycallgraph so I decided to give it a try on following code:

#!/bin/env python

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2, 100)

# The first call to plt.plot will automatically create
# the necessary figure and axes to achieve the desired plot.
plt.plot(x, x, label='linear')

# Subsequent calls to plt.plot re-use
# the current axes and each add another line.
plt.plot(x, x**2, label='quadratic')
plt.plot(x, x**3, label='cubic')

# Setting the title, legend, and axis labels also automatically
# use the current axes and set the title,
# create the legend, and label the axis respectively.
plt.xlabel('x label')
plt.ylabel('y label')

plt.title("Simple Plot")

plt.legend()

plt.show()

This code is from my another question where I've been asking about hierarchy in matplotlib, and I get the following answer:

If you're really keen to see how the auto creation is done - it's all open source. You can see the call to plot() creates an Axes instance by a call to gca() in the code here. This in turn calls gcf(), which looks for a FigureManager (which is what actually maintains the state). If one exists, it returns the figure it's managing, otherwise it creates a new one using plt.figure(). Again, this process to some degree inherits from matlab, where the initial call is usually figure before any plotting operation.

First, I was trying pycallgraph with graphviz option, but it gives me following error:

$ pycallgraph graphviz -- matplotlib.py
libpath/shortest.c:324: triangulation failed
libpath/shortest.c:192: source point not in any triangle
Error: in routesplines, Pshortestpath failed
Segmentation fault
Traceback (most recent call last):
  File "/usr/local/bin/pycallgraph", line 26, in <module>
    exec(__file_content)
  File "/usr/local/lib/python2.7/dist-packages/pycallgraph/pycallgraph.py", line 38, in __exit__
    self.done()
  File "/usr/local/lib/python2.7/dist-packages/pycallgraph/pycallgraph.py", line 81, in done
    self.stop()
  File "/usr/local/lib/python2.7/dist-packages/pycallgraph/pycallgraph.py", line 90, in generate
    output.done()
  File "/usr/local/lib/python2.7/dist-packages/pycallgraph/output/graphviz.py", line 112, in done
    'code %(ret)i.' % locals())
pycallgraph.exceptions.PyCallGraphException: The command "dot -Tpng -opycallgraph.png /tmp/tmpObsZGK" failed with error code 35584.

Second I've tried to generate gephi format and it worked:

$ pycallgraph gephi -- matplotlib.py

When I've opened this in gephi I get huge graph (Nodes: 1062, Edges: 1362) which was almost useless and I cannot saw anything useful here. So I've tried limit the output:

$ pycallgraph --max-depth 5 gephi -- traceme.py

This gives me graph with 254 nodes and 251 edges which was basically also useless because I still cannot saw nothing useful here. So, I've decided to try following:

egrep -i 'gcf|gca|plot' pycallgraph.gdf

But it returns me nothing. Then I've started wondering what exactly is pycallgraph tracing and I've made this hello world:

#!/bin/env python
print "This line will be printed."

And I've run it with (graphviz):

pycallgraph graphviz -- hello_world.py

The output (read from png file that was generated) was:

__main__ ---> <module>
  1. What tool can I use to get similar answer as I've referred? In another words, how can I know that this is the order of calling the functions: plot() -> gca() -> gcf()?
  2. What is pycallgraph actually tracing?
  3. Why hello world example is working with graphviz option but more complex example is working only with gephi option?
  4. How to preserve the DOT format which is pycallgraph generating and passing to graphviz?
Community
  • 1
  • 1
Wakan Tanka
  • 7,542
  • 16
  • 69
  • 122
  • It seems you want a controlled stack trace of program execution. That is what the traceback module is for. See https://docs.python.org/2/library/traceback.html. –  Jun 28 '15 at 21:47
  • @TrisNefzger thank you for reply, as I can see the `traceback` module is mainly for error handling or am I wrong? I've found `trace` module which is close to what I want except I cannot determine which function is calling which and there is also absence of arguments. – Wakan Tanka Jun 28 '15 at 22:40
  • Traceback has functionality for working with the stack without exceptions. There is a short tutorial on this at http://pymotw.com/2/traceback/ in the section 'Working With the Stack' showing use of its print_stack(), format_stack() and extract_stack() functions. –  Jun 28 '15 at 22:48
  • This is weird approach IMHO. If you look at the provided example then you'll see the `call_function` (function that is being traced) needs to have the traceback function (the function that is tracing) as it's first argument. This means that when I want to trace some module I have to overwrite it's functions. – Wakan Tanka Jun 28 '15 at 23:50
  • Playing with sys.settrace looks interesting http://stackoverflow.com/questions/8315389/how-do-i-print-functions-as-they-are-called – Wakan Tanka Jun 29 '15 at 00:19
  • How to preserve the DOT format which is pycallgraph generating and passing to graphviz? I just wrote something to that effect - https://gist.github.com/jpeyret/33739f6cd99f6108ad5046bd47df5a16 – JL Peyret Jun 16 '18 at 17:42

0 Answers0