2

I'm just starting to programming, so I may not know the proper way to ask a question. Please understand this first.

In the book or on the Internet, it is said that exceptions are used to prevent the interpreter from stopping and crashing. But I can't tell the difference between when I must use an exception and when I must use an if-else. For example, let's say I have the following code:

a, b, c = 1, 2, 3
def join_strings(arr):
    global a, b, c
    a = arr[0]
    b = arr[1]
    c = arr[2]  # IndexError: list index out of range
    return arr[0] + arr[1] + arr[2]
join_strings(["A", "B"])

Of course, I can prevent crashing by using an exception. But if I need rollback i.e. a, b, c should be 1, 2, 3 respectively if fails, I will have to write code to find out why the exception occurs, check how far the state has progressed, and rollback it again. How is this different from checking the value of len(arr) rather like below? For example, what is the proper way?

# option 1: Just wrap it with try/catch
# Should check status and needs rollback if I need
def join_strings(arr):
    try:
        a = arr[0]
        b = arr[1]
        c = arr[2]  # IndexError: list index out of range
    except:
        ...
 
# option 2: do some check to avoid rollback process
def join_strings(arr):
    if len(arr) < 3:
        raise IndexError("list index out of range")

# option 3: same with option 2 but return somevalue
def join_strings(arr):
    if len(arr) < 3:
        print('error. you should check this')
        return -1
    else:
        ...

What is the proper way to use exception? Programming books explain what exceptions are, but I don't understand exactly why they are needed or how to use them.

I googled and found Joel's Blog. But I'm a beginner, so I don't know what it means, and I don't even know a suitable search term on Google. Can you give me a more understandable use case or rule of thumb?

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
mobius
  • 29
  • 3
  • 1
    There are conditions which it would be impractical, or even impossible, for your code to test for. – Scott Hunter Jun 29 '22 at 12:36
  • 2
    This is opinion based, but the prevalent opinion in the Python community is that asking for forgiveness is easier than to ask for permission. This means that you don't test values before you use them, but rather use exception handling for control flow. Of course, there are scenarios where sanitizing data is necessary before using it, mostly when it comes to user input and/or security. – timgeb Jun 29 '22 at 12:38
  • @timgeb Sorry. I didn't understand exactly. Do you mean "how and when to use an exception" is a style rather than a rule? – mobius Jun 29 '22 at 12:44
  • 2
    That's very open ended and opinion based question, so not a good fit for SO. In general exceptions aren't much more *functionally* different than if-elses. But exceptions are much more clear about what is their purpose. In very simple terms, if you don't know to handle some state your code is currently in, raise an exception. – matszwecja Jun 29 '22 at 12:44
  • 1
    yes, it's a style. But most Python programmers seem to adopt the style of rather dealing with an exception than to test every possible case where a function might fail before calling it. (And as others have pointed out, sometimes you can't even test this.) – timgeb Jun 29 '22 at 12:50
  • 1
    Thanks to you, I am able to find the terms EAFP, LBYL and PEP 463[link](https://peps.python.org/pep-046/). Just knowing the right words to ask the question has been a huge help to me. Thank you very much for your kind reply. – mobius Jun 29 '22 at 12:55

2 Answers2

1

Some errors can not be checked beforehand.... for example, if you are connecting to another server it might be down right now. In those cases, you have to follow the try/except pattern.

In cases where you CAN test whether a failure might occur ahead of time, you may. The difference between the options in your question I would say is purely style. However, there can be performance implications, see this question.

Some more background is found in PEP8, look for the word try here.

Cargo23
  • 3,064
  • 16
  • 25
1

next- os only my oppinion:

The use of exceptions allows the program to work correctly as expected, in case of unexpected data.

  1. Firstly, we cannot always be sure that we will receive correct data for processing and that we have provided for all possible options for errors.
  2. Secondly, if something unexpected comes up, it would be good for program support if we fix it. And in general, it can be useful for debugging in future.

I will try give a couple of examples for both cases:

  1. We want to receive data from the server, but the connection is unexpectedly terminated during the data transfer. If we do not provide for the possibility of an exception, then we will get an abnormal termination of the program. If we caught an exception, we can handle it and decide what to do next. Moreover, the design try- except Exception allows you to specify different behavior for different types of exceptions.

  2. We can record exception calls in the logs in order to provide for new outcomes. This can be especially useful for poorly predictable exceptions and beginners.

MNK
  • 56
  • 2