Use assert() carefully!

Please, don’t use Python  assert(statement) for things other than debugging in any more or less significant script.
Why?

Python compilers have optimisation modes. Those modes make code run faster by stripping down some things that are not really necessary for the code to function. For example, those are function docstrings – they’re omitted in optimisation mode just for the sake of optimisation.
Python interpreters also have a boolean called __debug__ that is defined by the compiler inside each script executed. It cannot be changed by the script itself. It is set as True all the times except for optimisation modes, where this boolean is False. Why we need this boolean? Just you wait.
Originally, assert was thought as a tool for the debugging. Actually, it still is. How does it work? Well, the original function’s code looks like this:

def assert(expression):
    if __debug__:
        if not expression: raise AssertionError

So, if __debug__ is False, there might be no AssertionError raised where you expect it. Let’s see a small script that the officers of some top secret nuclear attack site use:

#Used mainly for preparing tea 
#Nukes everybody if argument "nukeeverybody" is given
import sys
import nuke
import tea
try:
    assert(sys.argv[1] != "nukeeverybody") 
except AssertionError:
    teacup = tea.Tea(volume="cup")
    teacup.boil_water()
    teacup.brew_tea()
    teacup.bring_to_officers()
else:
    our_nuke = nuke.Nuke(target=nuke.targets["everybody"]) #OH MY GOD
    our_nuke.prepare() #WHY THIS
    time.sleep(3) #WE'RE GOING TO DIE
    our_nuke.launch() #At least we used objects where they were really aproppriate

Suppose that somebody made all the technical officers at the rocket silo recompile all their Python interpreters so that by default they use the optimisation mode. Then one of them wants some tea and launches bringtea.py… Assert behaves as if the statement is True, even though it isn’t. So the code passes straight to the “else” block and the code there gets executed…

Until time.sleep(), as “time” isn’t imported 😉 Still, nuke is prepared for the launch, who knows, what bad could happen due to that. Also, officers don’t get any tea.

Don’t use assert for things like checking arguments and such. It wasn’t prepared for anything other than testing and debugging and thus may misbehave on other occasions.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s