Should I always use Try catch to fix mistakes?

Asked

Viewed 203 times

5

Sometimes when I know something may fail in my system I do a validation using if, equal is below:

lista = [1,2,3]
#um número que esteja entre os indices da lista
numero = int(input(f'Digite um número entre 0 e {len(lista)-1}: '))
#se o número for maior ou menor que os indices da lita
if numero > len(lista)-1 or numero < 0:
    print('Algo deu errado')
else:
    #se der certo
    print(lista[numero])

However, I can also use the try except to handle/catch errors. Example:

lista = [1,2,3]
#um número que esteja entre os indices da lista
numero = int(input(f'Digite um número entre 0 e {len(lista)-1}: '))
try:
    #se der certo
    print(lista[numero])
except:
    print('Algo deu errado.')

Which of these ways to treat errors is best or most recommended?

3 answers

6


There are controversies. It depends on what you want and the style you adopt. The Python community prefers the call EAFP instead of LBYL (reference). Of course you have to analyze each case, but it makes sense for the type of language.

I think this is a little abusive, but it’s how the language defined it should communicate problems in certain situations. So if you do more or less like this it is correct in this language. But even in it there can be too much abuse. Some people start using exception for everything, even when they shouldn’t, even in style pythonic.

Some people will start using exception where a if works as well or better. For me your initial code is more right to do this validation. It seems to me that in the case of your code it makes no sense to use the exception instead of the if. It seems to me that this is the case with your code, but you can’t nail which is more right.

The second one is slower than the first if it goes wrong, but the first one can be slower if it doesn’t. For a simple code like this doesn’t make the slightest difference, but it’s good to know that, in something with a loop and millions of data can make a good difference, it depends on whether the data is more wrong or more right. Would have to measure.

I think the first most semantic, you show that you care specifically about that before you give the error. But it is still readable the second code.

Actually the second code is not so good, but because it was misspelled. Well written the readability changes little. Some will say that even the second would be more expressive. It would look like this:

lista = [1, 2, 3]
numero = int(input(f'Digite um número entre 0 e {len(lista)-1}: '))
try:
    print(lista[numero])
except IndexError:
    print('O número digitado está fora da faixa aceita')

Capture whichever exception is a mistake even if it works, because even another type of error that is not what you are prepared to deal with there would fall in the except. What would make the codes not equivalent since the first is very specific and the second treats any error.

Even in the first code the message should be more specific, does not change the final result but makes your application better.

I said that I do not like to treat validation as an exception and can search the site to see that I talk about it in many posts. But in Python I find less problematic because it is a language of script.

There is an extra sentence: if the person type a letter it is wrong in both cases.

It takes a little more work to deal with all kinds of problems in the first way, unless you create a function that does this and always calls it in place of the input() what a lot of people do. There was a time when it was one of the first things a programmer would do when he learns to code. Today as in general people only learn to follow cake recipes and do not use creativity, do not think about how to solve something better, even if it takes a little more work, but is a more appropriate solution.

It can be like exercise, rather than a lot of things they ask to do out there because it’s not just coding, it’s thinking about the problem, finding a complete and generic solution, it has to be well designed.

But it really takes less work in the language to let the exception burst and deal with because it doesn’t have good tools to deal with before the mistake happens.

And treating if you typed a number is much more complicated to do (I would, but I’m not recommending for everyone).

Something like that seems better for most pythonists:

lista = [1, 2, 3]
try:
    numero = int(input(f'Digite um número entre 0 e {len(lista)-1}: '))
    print(lista[numero])
except ValueError:
    print('Não foi digitado um número')
except IndexError:
    print('O número digitado está fora da faixa aceita')

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

I think you should use whatever you think is best, but it should be consistency. So even if it is difficult and you have to create a library to deal with it, if it will validate before giving the error, you should do it at all, you cannot use exception to check if the data is one of the characters you expect and use condition to check if it is within the required range. Sure, it can, but it’s weird. Both are not exceptional cases, so the exception is not good, but if you choose the exception do in both. Invalid data and something exceptional that happened are different things.

  • I don’t know why, but I think that answer left some pythonists embarrassed kkk

  • @Jeanextreme002 I don’t know much about the community so I don’t get the joke, can you explain?

  • Indirectly you kind of called the Pythonists sloppy for using try-except for everything kkk. I know it was not the intention but it seems in the answer and I honestly agree with that. Python really gives a lot of freedom and many programmers.

  • It’s not sloppy because it was consciously chosen to do it. They think it’s good. At least there’s a lot of content citing it. Sloppiness would be doing anything without thinking. Having an option that I do not agree with is not the same as accepting any option. But I think there’s inconsistency, and that kind of goes for any community that thinks the exception should be used for validation, and it’s one of the reasons that it should be clearer what validation is and what’s exceptional.

2

The best way to treat errors is to make sure there are no errors. The recommended is to use the block try-except only when you don’t have control of something that can possibly generate an exception or when the scan is too extensive and make up for more letting the error happen to capture the exception.

In your code for example, there is a case where you can use a conditional and another case where you can use the try-except to capture an exception.

In the first part of the code, you receive the user input expecting it to be numerical. But have you thought about what would happen if the user did not type a number but a letter?

This is the kind of situation where you should use the block try since in this case, check whether the data is numerical or would not be much more work than capturing the exception.

try:
    entrada = input(f'Digite um número entre 0 e {len(lista)-1}: ')
    numero = int(entrada)
except:
    print("Você deve digitar um valor numérico.")
    numero = -1

In the second part of the code, it is not necessary to use the try because you can very well with a simple conditional check the value the user entered.

if 0 < numero < len(lista):
    print(lista[numero])
else:
    print("Algo de errado não está certo =/") 

See also this other example. In the code below, the function receives a text and returns a dictionary expecting the text to be a JSON.

But how could we verify that the text is really correct? In this case, it is much better to use a try-except to be ready to capture an eventual exception in the code.

def get_json_from(text):

    try: return json.loads(text)
    except: return None
  • 4

    Unused if to check whether or not a file exists. You expose your code to a running condition called Toctou(Time Of Check to Time Of Use) which occurs when code is checked for the existence of the file but an event external to the code removes the file soon after the verification that allows its code to be exploited maliciously. Read How to identify the anti-standard TOCTOU? How to avoid/remove it?

  • 1

    Okay, I’ll change the example and read this article about the TT.

0

Regarding the command itself "Try-catch" independent of the adopted programming language and based on my personal experience when discovering and applying this command in my logics, I recommend its use when you want to run a block of actions. For example in methods that must be executed sequentially, where the execution of one depends on the result returned from the previous one. This way inside the Try you put the whole procedure to be performed in case of success of all actions and in the catch block you will only return the exception found without knowing exactly where was launched the exception.

For this you must in all your methods called within the Try block throw an exception (throw Exception) when some unexpected behavior occurs with the message describing the identified error and code if necessary, by identifying any exception the Try block will be stopped immediately and whatever is in the catch will be executed, protecting the commands that from there existed within the Try. In addition to these benefits it is clear that the code is more organized this way, separating all expected behavior (Try) from unexpected behavior (catch). In your case, I see no problem using the if-lse.

Note: I’m sorry for not giving examples with Python for not having experience with the language, but I thought that this question could be answered in a general way, related to programming.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.