[Tutor] Strange IndexError

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Thu Jun 2 21:00:58 CEST 2005

On Thu, 2 Jun 2005, Willi Richert wrote:

> my app is a Pyrobot (http://emergent.brynmawr.edu/~dblank/pyro/)
> simulation which connects to PlayerStage (playerstage.sf.net)  to
> simulate three Pioneer robots. These are controlled using NeedBrain.py.
> In parallel to the three NeedBrains there is one MonitorBrain running
> for some management tasks, so I have
>  four parallel running classes.

Hi Willi,

I think you may want to bring this up on comp.lang.python: I have a strong
feeling I'm in over my head.  *grin* The experts on comp.lang.python
should be able to better pinpoint the exact problem.

The code that prints that peculiar error message is at the very core of
Python's object implementation in doing object equality checking:

/*** Objects/object.c, about line 441 in Python 2.4 source ***/
/* Helper to warn about deprecated tp_compare return values.  Return:
   -2 for an exception;
   -1 if v <  w;
    0 if v == w;
    1 if v  > w.
   (This function cannot return 2.)
static int
adjust_tp_compare(int c)
	if (PyErr_Occurred()) {
		if (c != -1 && c != -2) {
			PyObject *t, *v, *tb;
			PyErr_Fetch(&t, &v, &tb);
			if (PyErr_Warn(PyExc_RuntimeWarning,
				       "tp_compare didn't return -1 or -2 "
				       "for exception") < 0) {
				PyErr_Restore(t, v, tb);

We can reason that PyErr_Occurred() somehow returned true, and that the
error information is being captured in C code throught the 't', 'v' and
'tb' variables.  Those three variables are ultimately responsible for
what's printing out:

    IndexError: tuple assignment index out of range

and the output that talks about 'tp_compare' shows up because of the
PyErr_Warn call.  That explains why we see both error messages.

I'm staring at the code a little more; there's a bit of code around line
229 that bothers me a bit:

            self._markerObject = self.get("robot/fiducial/id")(self.marker)
            if not self._markerObject:
                self._markerDist = 1000.0
                self._markerDist = self._markerObject.range

My hypothesis now is that the equality check against the type of
self._markerDist is raising an error, which would require self._markerDist
to be something unusual.  I know, I'm reaching, but let me see how far
this goes.  *grin*

I don't see anything else that assigns to self._markerDist in any other
part of the code.  In the code above, I see in the 'else' block that
self._markerDist is being assigned to 'self._markerObject.range'.  What
type is 'self._markerObject', and what type is 'self._markerObject.range?
Do you mind adding some code to print those out?

I can't assume that 'range' is a number, since 'range' is being used in
all sorts of contexts, especially in the pyro source code.  For example,
pyro.PyroHierarchy has the following comment:

class PyroHierarchy (object):
    A wrapper class for the pyro devices hierarchy.
    An instance of this class represents a node of the hierarchy,
    with an attribute for every subnode.
    Getting an attribute is equivalent to using robot.get .
    Setting an attribute is equivalent to using robot.set .
    Numeric nodes can be accessed as list elements.

    Examples of use:
      h.robot.range.all               # returns another PyroHierarchy
      h.robot.range.name              # return a string
      h.robot.range.all.value         # return a list of numbers
      h.robot.range[1].value          # returns a number
      h.robot.range[1:4]              # returns a list of PyroHierarchy
      h.devices.gripper.command = "open" # issues command "open" to

so I strongly suspect that this 'range' object is something much richer
than a float.

Something like:

     print self._markerDist, type(self._markerDist)

might help us see what's going on better.

Best of wishes to you!

More information about the Tutor mailing list