PyWart: NameError trackbacks are superfluous

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Mar 16 19:48:01 EDT 2013


On Sat, 16 Mar 2013 21:19:34 +0000, Oscar Benjamin wrote:

> On 16 March 2013 18:27, Rick Johnson <rantingrickjohnson at gmail.com>
> wrote:
>>
>> Sometimes many levels of trace messages can be helpful when detecting
>> bugs, however, in the case of NameErrors,  these "nuggets" ejected from
>> deep within the bowls of the Python interpreter are nothing more than
>> steaming piles of incomprehensible crap!
>>
>> We don't need multiple layers of traces for NameErrors. Python does not
>> have *real* global variables; and thank Guido for that! All we need to
>> know is which module the error occurred in AND which line of that
>> module contains the offensive lookup of a name that does not exist.
> [SNIP]

/head-desk

Is Rick still pushing these stupid "PyWart" ideas?


> NameErrors can occur conditionally depending on e.g. the arguments to a
> function. Consider the following script:
[...]

Correct, although in your example, simply pointing at the relevant line 
of code is enough to establish the error.

But that's an easy case. Tracebacks aren't printed because you need them 
to fix the easy bugs. Tracebacks are printed so you have a hope of fixing 
the hard bugs. NameError is no different in this than any other 
exception, and the Zen applies:

Special cases aren't special enough to break the rules.

NameErrors are exceptions like any other. They aren't special enough to 
suppress the full traceback when a NameError occurs. In the easy cases, 
you can just ignore the full traceback, and no harm is done. In the hard 
cases, you will need it.

Since name bindings ("variables") in Python are dynamic, not static, 
whether or not a name exists at any time can depend *when* and *how* you 
call a line of code, not just which line of code. That is, whether or not 
a line of code will raise NameError can depend on which lines of code are 
called before it, and that depends on the function call chain shown by 
the traceback.

Here's a truly trivial case where code will succeed or fail depending on 
the order of function calls.

def display():
    print("spam = %d" % spam)

def start():
    global spam
    spam = 23

def stop():
    global spam
    del spam

def run():
    print("*** Succeeds ***")
    start()
    display()
    stop()

def fail():
    print("*** Fails ***")
    start()
    stop()
    display()


run()
fail()


It's not enough to know that the print line in display() fails, because 
that's merely the side-effect. The actual problem occurs in the caller, 
fail(). If NameError suppressed the traceback, that would be more 
difficult to solve.



-- 
Steven



More information about the Python-list mailing list