Enhanced try() function

Consider this code:

try:
    # potential erroneous statement
    # other statements dependable on the above statement
except:
    pass

Meaning, I have a statement that may cause error and next statements should execute only if no error occurs. However, I don’t need some statements that will execute if an error occurs. In this case, I have to put a simple pass statement in the exception block.

A lot of times this case is encountered and I think the two unnecessary except block statements can be eliminated by adding the following try function to the core module.

def try(self, statement) -> bool:
    try:
        eval(statement)
        return True
    except:
        return False

This is how it works:

tup = (1, 2, 3)
statement = str(tup.append(4))      # potential erroneous statement
try(statement):
    # statements that execute if no error occurs
    # for example
    print (" added successfully")

If there already exists an alternative to this, please let me know. Else, I would like to consider this to be added as an enhanced try() function to the core module of python.

This sounds like you want the else clause of try statements: Python Exceptions: An Introduction – Real Python

4 Likes

Hi Sanket,

You wrote this code:

try:
    # potential erroneous statement
    # other statements dependable on the above statement
except:
    pass

Please don’t write code like that. This is nearly always a terrible
idea.

1 Like

Hi Steven,

I understand what you want to say, that if any other exception occurs in the try block other than what we were expecting, that makes the code terribly hard to debug.

Thanks for pointing that out, because on the brighter side, my proposed enhanced try() function overcomes that misconception too. Because it takes targets only one statement at a time.

Jean, I get it. But using else statement is again going to increase the code size, which is the main concern here.

Is it this long though?

try:
    (1, 2).append(4)
except AttributeError:
    print("Nope")
else:
    print("Added successfully")

I have seen few cases where you want to execute code when no error occurs but you don’t want to do anything when there is an error.

1 Like

Maybe I’m missing something, but your approach increases code size and (IMO) makes the code less readable. Also, @steven.daprano is quite right regarding except:

Pythonic

# 6 lines:
try:
    fn()
except SomeException:  # catch specific exceptions
    pass
else:
    success()

“try function”

# 10 lines
def try(stmt):
    try:
        eval(stmt)
        return True
    except:  # oops, catch all => bad coding!
        return False

stmt = str(fn())
if try(stmt):
    success()

AFAICS, the pythonic way is both compact and readable, and it correctly catches specific exceptions.

1 Like

I think the contextlib.suppress() context manager does pretty much what you want in a much more idiomatic way than the try() function you propose.

5 Likes

Oh, I’d forgotten about contextlib.suppress(); thanks for the reminder :smile:

Even one statement can contain many different possible failures.

a = mymodule.function(arg, number + 1, mylist[0])

could fail with NameError, AttributeError, TypeError or IndexError and
that’s even before the function gets called, which could fail with
anything.

The problem with try…except is not that there can be more than one
statement inside the try. The problem is that the except clause will
hide unexpected errors, that is bugs. Your code will silently
suppress the error and go on to do the wrong thing.

To quote Chris Smith:

“”"
I find it amusing when novice programmers believe their main job is
preventing programs from crashing. … More experienced programmers
realize that correct code is great, code that crashes could use
improvement, but incorrect code that doesn’t crash is a horrible
nightmare.
“”"

The Therac-25 machines killed people because their software didn’t
crash when it should have.

Your code might not be as critical as the Therac control software, but
the princple is the same: code that silently does the wrong thing is a
nightmare to debug when you eventually discover that it is producing
garbage output instead of what you wanted.

With very, very few exceptions, catching “any exception at all” is the
wrong thing to do. And for those few exceptions, being clear and
explicit about what we are doing, with a full try…except block, is not
a hardship unless you are trying to win a code golf competition.

Regardless of whether it is written with an explicit “except: pass” or
implicitly with your suggested syntax, catching everything is not
something that we should want to encourage. We shouldn’t want to make it
easier to do than it already is.

2 Likes

Why do you care so much about code size that it is “the main concern”?

What do you mean by code size?

  • the number of bytes in your source code;

  • the number of lines in your source code;

  • the number of bytes in the compiled .pyc file;

  • something else?

How many try...except blocks do you have in your code that this will
be anything but a trivial extra number of lines of code?

I have just randomly picked out three small projects I am working on,
just under 1000 lines of code in total, and with one try…except
block between them. So if I added an else clause, that would increase
my code size by one line in a thousand.

My hard drive is pretty full at the moment, but I think even I can
afford an extra line of code or two.

1 Like

However, I don’t need some statements that will execute if an error occurs.

You probably do. At the very least, you can do something like this:

tup = (1, 2, 3)

try:
    tup[4]
except IndexError:      # I was expecting this one
    logger.warn()        # maybe log something
except Exception as e:  # I wasn't expecting this one
    print(e.__class__.__name__, e)  # maybe inform the user this way or more friendly
    logger.error(e)        # log the error, maybe do other clean up tasks in here
    raise
else:
    # All is well
    ...