tags:

views:

279

answers:

5

I often use python's assert statement to check user input and fail-fast if we're in a corrupt state. I'm aware that assert gets removed when python with the -o(optimized) flag. I personally don't run any of my apps in optimized mode, but it feels like I should stay away from assert just in-case.

It feels much cleaner to write

assert filename.endswith('.jpg')

than

if not filename.endswith('.jpg'):
    raise RuntimeError

Is this a valid use case for assert? If not, what would a valid use-case for python's assert statement be?

+7  A: 

If being graceful is impossible, be dramatic

Here is the correct version of your code:

if filename.endswith('.jpg'):
    # convert it to the PNG we want
    try:
        filename = convert_jpg_to_png_tmpfile(filename)
    except PNGCreateError:
        # Tell the user their jpg was crap
        print "Your jpg was crap!"

It is a valid case, IMHO when:

  1. The error is totally, 100% fatal, and dealing with it would be too grim to comprehend
  2. The assert should only fail if something causes the laws of logic to change

Otherwise, deal with the eventuality because you can see it coming.

ASSERT == "This should never occur in reality, and if it does, we give up"

Of course, this isn't the same as

#control should never get here

But I always do

#control should never get here
#but i'm not 100% putting my money where my mouth
#is
assert(False)

That way I get a nice error. In your example, I would use the if version and convert the file to jpg!

Aiden Bell
+1  A: 

Personally, I use assert for unexpected errors, or things you don't expect to happen in real world usage. Exceptions should be used whenever dealing with input from a user or file, as they can be caught and you can tell the user "Hey, I was expecting a .jpg file!!"

Corey D
+2  A: 

assert is best used for code that should be active during testing when you are surely going to run without -o

You may personally never run with -o but what happens if your code ends up in a larger system and the admin wants to run it with -o?

It's possible that the system will appear to run fine, but there are subtle bugs which have been switched on by running with -o

gnibbler
+9  A: 

Assertions should be used for expressing invariants, or preconditions.
In your example, you are using them for checking unexpected input - and that's a completely different class of exceptions.

Depending on the requirements, it may be perfectly OK to raise an exception on wrong input, and stop the application; however the code should always be tailored for expressiveness, and raising an AssertionError is not that explicit.
Much better would be to raise your own exception, or a ValueError.

Roberto Liffredo
Right. As I get better at programming, I find I understand more deeply *why* my code works, what the assumptions are, and I see more and more opportunities to use `assert` in this way.
Jason Orendorff
@Gattster: `if expr: raise ValueError` is a totally valid single line of code. Open a separate question if you have problems.
S.Lott
+2  A: 

Totally valid. The assertion is a formal claim about the state of your program.

You should use them for things which can't be proven. However, they're handy for things you think you can prove as a check on your logic.

Another example.

def fastExp( a, b ):
    assert isinstance(b,(int,long)), "This algorithm raises to an integer power"
    etc.

Yet another. The final assertion is a bit silly, since it should be provable.

# Not provable, essential.
assert len(someList) > 0, "Can't work with an empty list."
x = someList[]
while len(x) != 0:
    startingSize= len(x)
    ... some processing ...
    # Provable.  May be Redundant.
    assert len(x) < startingSize, "Design Flaw of the worst kind."

Yet another.

def sqrt( x ):
    # This may not be provable and is essential.
    assert x >= 0, "Can't cope with imaginary numbers"
    ...
    # This is provable and may be redundant.
    assert abs( n*n - x ) < 0.00001 
    return n

There are lots and lots of reasons for making formal assertions.

S.Lott
Thanks for providing examples of valid use-cases. I hope to see more up-votes on your answer to help validate that others share our opinion.
Gattster
+1, for a well thought out answer.
Aiden Bell
@Gattster: It's a minority opinion. Many folks claim that formal proof methods either (a) don't work or (b) don't apply to real-world problems. You won't see much validation for this position.
S.Lott
in the 2nd example, couldn't you just "assert someList"?
Steven Sproat
@sproaty: You could. The point of an assertion is to clarify the meaning of the code, not merely repeat it. So, an alternative (and more explicit) formulation seems to be of some value.
S.Lott