r0g wrote:
Dave Angel wrote:
r0g wrote:
<snip>

Maybe, although I recently learned on here that one can't rely on assert
 statements in production code, their intended use is to aid debugging
and testing really.

Hopefully, what you learned is that you can't use assert() in production
code to validate user data.  It's fine to use it to validate program
logic, because that shouldn't still need testing in production.

<snip>

DaveA



Well maybe I didn't quite get it then, could you explain a bit further?

My understanding was that asserts aren't executed at all if python is
started with the -O or -OO option, or run through an optimizer. If
that's the case how can you expect it to validate anything at all in
production? Do you mean for debugging in situ or something? Could you
maybe give me an example scenario to illustrate your point?

Cheers,

Roger.

You understand the -O and -OO options fine. But the point is that you should not use assert() for anything that will be properly debugged before going to the user. You use if statements, and throw's to catch the error, and print to stderr, or GUI dialog boxes, or whatever mechanism you use to tell your user. But those errors are ones caused by his data, not by your buggy code. And the message tells him what's wrong with his data, not that you encountered a negative value for some low level function.

I agree with Steve's pessimistic view of the state of most released software. But if you view a particular internal check as useful for production, then it should be coded in another mechanism, not in assert. Go ahead and write one, with a UI that's appropriate for your particular application. But it should do a lot more than assert does, including telling the user your contact information to call for support.

           def production_assert(expression, message):
                        if  not expression:
dialog_box("Serious internal bug, call NNN-NNN-NNNN immediately", message)


For an overly simplified example showing a user validation, and an assert :

import sys
def main():
   try:
       text = raw_input("Enter your age, between 1 and 22 ")
       age = int(text)
   except  ValueError, e:
       age = -1
   if not 1 <= age <= 22:             #not an assert
       print "Age must be between 1 and 22"
       print "Run program again"
       sys.exit(2)
   grade = calc_grade(age)
   print "Your grade is probably", grade

table = [0, 0, 0, 0, 0, "K", "First", "2nd", 3]
def calc_grade(age):
   """ calculate a probable grade value, given an
   i2nteger age between 1 and 22, inclusive
   """
   assert(1 <= age <= len(table))
   grade = table[age]    #assume I have a fixed-length table for this
   return grade

main()

Note a few things. One I have a bug, in that the table isn't as big as the limit I'm checking for. With defensive coding, I'd have another assert for that, or even have the table size be available as a global constant (all uppers) so that everyone's in synch on the upper limit. But in any case, the test suite would be checking to make sure the code worked for 1, for 22, for a couple of values in between, and that a proper error response happened when a non-integer was entered, or one outside of the range. That all happens in separate code, not something in this file. And the test suite is run after every change to the sources, and certainly before release to production.

Next, see the docstring. It establishes a precondition for the function. Since the function is called only by me (not the user), any preconditions can be checked with an assert. An assert without a supporting comment (or docstring) is almost worthless.

And finally, notice that I check the user's input *before* passing it on to any uncontrolled code. So any asserts after that cannot fire, unless I have a bug which was not caught during testing.

All opinions my own, of course.

DaveA

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to