473,385 Members | 1,351 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

painful debugging: techniques?

Hello, I've been using python for about 3 months now. Prior to that I did
C++ for over 5 years. I'm wondering if my debugging techniques are too C++
oriented.

E.g., it took me about 9 hrs of debugging to figure out that the second
parameter to weakref.ref() was being passed as None. This is odd because the
second parameter is optional, yet its default value is not documented, so I
assumed that passing None would be fine, and then I forgot that I was doing
that. It took that long mostly because the exception message was "Exception
TypeError: 'NoneType not a callable' in None being ignored", ie it was being
ignored and function from which it was being raised was unknown to Python
(somehow), *and* it was only being raised upon exit of the test (cleanup).
So I had no way of knowing where this was being raised. It was nasty.

I'm wondering if there are tricks people use to track down problems like
this.

Thanks,

Oliver
Jul 18 '05 #1
5 1455
> I'm wondering if there are tricks people use to track down problems like
this.


I do two things. One is that I catch exceptions and print out the
variables for each frame, in addition to the traceback. The recipe
is at http://aspn.activestate.com/ASPN/Coo...n/Recipe/52215

The second thing is that I never start the program in the debugger.
If I actually need to debug somewhere, I add the following line:

import pdb ; pdb.set_trace()

You will then pop into the debugger at that point, and can step
through the code. The above statement can be inside an if
or any other condition, so I only triggers at the point that
is relevant.

Roger
Jul 18 '05 #2
Humpty Dumpty wrote:
Hello, I've been using python for about 3 months now. Prior to that I did
C++ for over 5 years. I'm wondering if my debugging techniques are too C++
oriented.

E.g., it took me about 9 hrs of debugging to figure out that the second
parameter to weakref.ref() was being passed as None. This is odd because
the second parameter is optional, yet its default value is not documented,
so I assumed that passing None would be fine, and then I forgot that I was
doing that. It took that long mostly because the exception message was
"Exception TypeError: 'NoneType not a callable' in None being ignored", ie
it was being ignored and function from which it was being raised was
unknown to Python (somehow), *and* it was only being raised upon exit of
the test (cleanup). So I had no way of knowing where this was being
raised. It was nasty.

I'm wondering if there are tricks people use to track down problems like
this.


The best strategy would have been to avoid the error altogether :-)
Python makes that easy; just test a chunk of code on the command line:
import weakref
class X: .... pass
.... def cb(a): print "callback" .... x = X()
w = weakref.ref(x, cb)
del x callback x = X()
w = weakref.ref(x, None)
del x

Exception exceptions.TypeError: "'NoneType' object is not callable" in None
ignored

The next best thing is to have a proper test suite and making only small
changes to your program, so that you can easily attribute an error to a
newly added chunk of code. IMHO this is the most promising aproach for
anything comprising more than one module. I admit that I don't know how to
devise test to discover your problem.

So what if all else fails? Let's stick to your example.
I would see not getting a traceback as a strong hint that something unusual
is going on. In this case you can leverage the fact that python is open
source and search for the place where the error message is generated.
Looking for "%r ignored" and "%s ignored" in *.py of Python's source
distribution yields no result. At this point I would extend the search to
"ignored" in the C source: 48 hits, but most of them in comments. The one
in error.c seems promising. Unfortunately the comment in
PyErr_WriteUnraisable() gives the "wrong" __del__() example, so you need
one more iteration to hunt for PyErr_WriteUnraisable. As the variable names
are well chosen, the match in weakrefobject.c
(PyErr_WriteUnraisable(callback);) gives you a strong clue.

I admit this is tedious and that I had a headstart as you already provided
the connection to weakref, but I reckon that this approach would still take
less than one hour. As a hidden benefit, you learn something about Python's
architecture. Also, in my experience your problem is a particularly hard
one to track down (as far as pure Python is concerned).

At last, what I would call the Columbus approach: do you really need
weakrefs in your application, or is the error an indication that you are
introducing unnecessary complexity in your app? Few eggs actually need to
stand on their tip :-)

Peter

Jul 18 '05 #3
"Roger Binns" <ro****@rogerbinns.com> wrote in message news:<a3************@home.rogerbinns.com>...

I do two things. One is that I catch exceptions and print out the
variables for each frame, in addition to the traceback. The recipe
is at http://aspn.activestate.com/ASPN/Coo...n/Recipe/52215


I think this will not work for the original poster's case. His
exception happens at the moment of garbage collection, out of his
control. That is, the exception is not coming from one of his
statements, so he can't wrap a try...except block around it. Example:

import weakref

class A: pass

def f():
a = A()
w = weakref.ref(a, None)

try:
f()
except:
print 'This will never be printed'

--------------------------

The original poster spent 9 hours to find the source of this bug. So
it is a tough problem, and it may well happen to other people. The
question now is: how can we stop this from happening to other people?

This bug does not seem to be catchable by sys.excepthook, which makes
it even tougher.

So far, I think Peter Otten's approach (search through the source
code) may be the most practical way. The fact that this bug cannot be
caught with sys.excepthook should probably be considered a bug in
Python?

I guess the only consolation is that this kind of system bugs don't
seem to happen too often. :)

regards,

Hung Jung
Jul 18 '05 #4

[Hung Jung]
The question now is: how can we stop this from happening to other people?
[...] So far, I think Peter Otten's approach (search through the source
code) may be the most practical way.


Make weakref.ref() check that its second argument is a callable?

(I know, "patches welcome" 8-)

--
Richie Hindle
ri****@entrian.com
Jul 18 '05 #5
"Humpty Dumpty" <ol***************@utoronto.ca> writes:
I'm wondering if there are tricks people use to track down problems like
this.


Perhaps not so much a trick as much as experience, but after working
with Python a bit, you'll find that any time you see something like
'NoneType not a callable' (or really any type) it pretty much says
that some object in your program should be a callable (function,
method, etc..) but is None (or the other type) instead. So in general
I'd immediately start looking for uses of None in my code (or ways in
which my code could generate None at runtime).

Now, depending on how much new code you had written before the error
started happening could help bound your search, and/or depending on
the complexity of the code being tested you might be able to insert
judicious prints at various points to check the value of objects. As
someone else pointed out, if you were proceeding in a test first
fashion you'd be at an advantage here since you would have high
confidence in existing code and that the error was introduced (or at
least tickled) specifically by whatever small amount of new code you
wrote since the last test execution.

Also, since the error was occurring on cleanup, it's related to
objects still alive at that time. So that would help indicate that
you should focus your search on objects that live throughout the
duration of the test, as opposed to more transient code.

Not sure how much that would have streamlined this case (it is fairly
tricky given the gap between source of error and eventual failure),
but it sounds like just focusing on your uses of None would have at
least selected the weakref.ref call as a potential issue fairly
quickly.

-- David
Jul 18 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: Java script Dude | last post by:
To all Mozilla JS Guru's (IE dudes welcome), I have spent the last three years developing complex DHTML applications that must work in IE 5.5sp2+ but I use Mozilla 1.3+** to do all my...
1
by: Sebastian | last post by:
Hi, I'm coming from a C/C++ background and wondering if there's a straightforward way to designate debugging code in a vb.net application? I'm accustomed to setting up a Preprocessor macro...
6
by: Maitre Bart | last post by:
One said: "The more time you'll spend on designing your app, the less you'll spend time debugging it." I agree with that, but chances are, you'll still need to debug it anyway! And the larger the...
5
by: phnimx | last post by:
Hi , We have developed a number of plug-in .NET Library Components that we typically deploy with our various applications by installing them into the GAC. Each of the applications contains an...
5
by: rn5a | last post by:
Can someone please suggest me a text editor especially for DEBUGGING ASP scripts apart from Microsoft Visual Interdev? I tried using Visual Interdev & created a project but Interdev generates...
2
by: robert112 | last post by:
my ie7 throws a 'page cannot be found' error when I leave my asp.net application no a debugging line. it gives me about 30 seconds worth of debug time before it throws that message and then when i...
0
jwwicks
by: jwwicks | last post by:
Introduction This tutorial describes how to use Visual Studio to create a new C++ program, compile/run a program, resume work on an existing program and debug a program. It is aimed at the...
2
jwwicks
by: jwwicks | last post by:
C/C++ Programs and Debugging in Linux This tutorial will give you a basic idea how to debug a program in Linux using GDB. As you are aware Visual Studio doesn’t run on Linux so you have to use...
6
kenobewan
by: kenobewan | last post by:
Congratulations! You are one of the few who realise that over 80% of errors are simple and easy to fix. It is important to realise this as it can save a lot of time. Time that could be wasted making...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.