cascading python executions only if return code is 0

Steven D'Aprano steve+comp.lang.python at
Tue Dec 24 04:41:22 CET 2013

Roy Smith wrote:

> So, here's the deeper question.  Is your issue strictly that -O elides
> assert statements?  That's a purely mechanical issue that could be
> solved by using the rather more verbose:
> if not condition:
>     raise AssertionError("....")
> Would you feel differently then?

Not quite. As I said in my initial rant, there's also the issue of using an
appropriate exception. Naming is important for comprehending what the code
does. Just as it's bad to do:

my_list = 42
my_str = [my_list * 2]

so it's bad to have badly chosen exceptions:

def handle_string(s):
    if not isinstance(s, str):
        raise ImportError("not a string")

Substitute AssertionError for ImportError:

def handle_string(s):
    if not isinstance(s, str):
        raise AssertionError("not a string")

and it's still wrong because the exception is misleading and/or confusing to
whoever has to deal with the code.

I've been known to use asserts inside private functions and explicit tests
inside public ones:

def func(x):
    if x <= 0:
        raise ValueError("x must be positive")
    return _func(x + 1)

def _func(x):
    assert x > 1
    return sqrt(1/(x-1))

If I think that the test is checking an internal invariant, assert is okay,
if not, it isn't. In this case, the fact that the actual calculation of
func(x) is factored out into a private function _func is purely an internal
implementation issue. I might refactor the code and move _func inline:

def func(x):
    if x <= 0:
        raise ValueError("x must be positive")
    x += 1
    assert x > 1
    return sqrt(1/(x-1))

in which case the assertion is obviously checking an internal invariant and
therefore acceptable. So it's still checking an internal invariant even
when the code is moved into a purely internal function.

The other rule I use is that if an assert might ever be triggered in the
normal run of the program, it shouldn't be an assert. In principle, we
should run Python code with -O in production.

(It would have been better if Python optimized code by default, and had a -D
switch to turn debugging on, including asserts. I believe that's what
languages like Eiffel do.)


More information about the Python-list mailing list