Okey, so there a few things that need to be explained where.
What is try-except used for?
It is used for catching errors raised by the program. Any code susceptible of raising an exception is inserted inside a try statement, and below that statement, any number of except statements with any single error that you want to catch.
try:
user_input = int(input('Give me a number: '))
except ValueError:
print('That is not a number!')
When should i use try-except?
It is not a good practice to use a try-except on every single line of code that could raise an error, because that may be half of it, or more. So when shall you use it? Simple, ask this question: Do I want to do any custom action with that error being raised? If the answer is yes, you are good to go.
Catching Exception or empty except
As I see in your example, you are using an empty except. Using an empty except statement will catch every single error raised that the surrounded code, which is similar (but not the same) as catching Exception. The Exception class is the superclass of every single built-in exception in the Python environment that are non-system-exiting (read here) and its generally a bad practice to catch either all exceptions with except: or Exception with except Exception:. Why? Because you are not letting the user (or even you, the programmer) know what error you are handling. For example:
fruits = ['apple', 'pear', 'banana']
try:
selection = fruits[int(input('Select a fruit number (0-2): '))]
except Exception:
print('Error!')
# But wait, are you catching ValueError because the user did not input a number,
# or are you catching IndexError because he selected an out of bound array index?
# You don't know
Catching multiple exceptions
Based on the previous example, you can use multiple try-except statements to difference which errors are being raised.
fruits = ['apple', 'pear', 'banana']
try:
selection = fruits[int(input('Select a fruit number (0-2): '))]
except ValueError:
print('That is not a number')
except IndexError:
print('That fruit number does not exist!')
Grouping exceptions
If there are two particular exceptions that you want to use for a same purpose, you can group them in a tuple:
fruits = ['apple', 'pear', 'banana']
try:
selection = fruits[int(input('Select a fruit number (0-2): '))]
except (ValueError, IndexError):
print('Invalid selection!')
Your case
Based on this information, add those try-except blocks to your code, and see what possible errors that could be raised during its execution, asking the previously recommended question Do I want to execute some custom action with this error?
Additionally
- There are
try-except-elsestatements. See here - There are
try-except-finallystatements. See here - You can combine them all in a
try-except1-except2...exceptN-else-finallystatement. - I recommend you get familiar with built-in errors why practicing this!
Explain Try / Except structure in practical examples?
Utilizing a Try / Catch method for Python Function Error Catching
python - What is more Pythonic way to handle try-except errors? - Software Engineering Stack Exchange
Best practices for try/except blocks in Python script.
Okey, so there a few things that need to be explained where.
What is try-except used for?
It is used for catching errors raised by the program. Any code susceptible of raising an exception is inserted inside a try statement, and below that statement, any number of except statements with any single error that you want to catch.
try:
user_input = int(input('Give me a number: '))
except ValueError:
print('That is not a number!')
When should i use try-except?
It is not a good practice to use a try-except on every single line of code that could raise an error, because that may be half of it, or more. So when shall you use it? Simple, ask this question: Do I want to do any custom action with that error being raised? If the answer is yes, you are good to go.
Catching Exception or empty except
As I see in your example, you are using an empty except. Using an empty except statement will catch every single error raised that the surrounded code, which is similar (but not the same) as catching Exception. The Exception class is the superclass of every single built-in exception in the Python environment that are non-system-exiting (read here) and its generally a bad practice to catch either all exceptions with except: or Exception with except Exception:. Why? Because you are not letting the user (or even you, the programmer) know what error you are handling. For example:
fruits = ['apple', 'pear', 'banana']
try:
selection = fruits[int(input('Select a fruit number (0-2): '))]
except Exception:
print('Error!')
# But wait, are you catching ValueError because the user did not input a number,
# or are you catching IndexError because he selected an out of bound array index?
# You don't know
Catching multiple exceptions
Based on the previous example, you can use multiple try-except statements to difference which errors are being raised.
fruits = ['apple', 'pear', 'banana']
try:
selection = fruits[int(input('Select a fruit number (0-2): '))]
except ValueError:
print('That is not a number')
except IndexError:
print('That fruit number does not exist!')
Grouping exceptions
If there are two particular exceptions that you want to use for a same purpose, you can group them in a tuple:
fruits = ['apple', 'pear', 'banana']
try:
selection = fruits[int(input('Select a fruit number (0-2): '))]
except (ValueError, IndexError):
print('Invalid selection!')
Your case
Based on this information, add those try-except blocks to your code, and see what possible errors that could be raised during its execution, asking the previously recommended question Do I want to execute some custom action with this error?
Additionally
- There are
try-except-elsestatements. See here - There are
try-except-finallystatements. See here - You can combine them all in a
try-except1-except2...exceptN-else-finallystatement. - I recommend you get familiar with built-in errors why practicing this!
try: code that might cause an errorexcept: code that runs if an error happenselse: runs if no error happensfinally: always runs (good for cleanup, closing files, etc.)
Example 1: Basic Example
try:
num = int("abc") # This will raise an error
print("Number:", num)
except ValueError:
print("Oops! Could not convert to int.")
Example 2:
try:
x = 10 / 0
except ZeroDivisionError:
print("You cannot divide by zero!")
except ValueError:
print("Invalid value!")
Example 3:
try:
x = 5 / 1
except ZeroDivisionError:
print("Division by zero not allowed.")
else:
print("Division successful:", x) # runs if no error
finally:
print("Always runs, even if there was an error.")
Example 4: General
try:
# risky code
x = 10 / 0
y = int("abc")
except Exception as e:
print("Error occurred:", e)
I am learning python and I've encountered the try / except part of it. I am struggling to understand when I would use this kind of code, probably because I am still very new and most of my code is small programs that have relied on conditional statments.
I guess in my brain I understand the logic of saying "try to do this but if it doesn't work just let it be and keep going with the code". My assumption is this is helpful on larger scale programs in wich you can't afford the time to make sure the code is fail proof and you need the code to buy you time to eventually go back once you have the fail proof option?
Was hoping someone could give me an example of a real life application or website and how this code could apply to it? Because I want to become comfortable with it but unsure how to.
TL,DR: Explain try/except in a practical example so I can understand when and where I would use it?
Thank you!
Neither of these is more Pythonic than the other. The examples are too trivial to say which is preferrable but it really all depends on how things should work.
Catch and logging/reporting an issue is just a hair's breadth away from squashing exceptions which is almost always a terrible idea. The only reason I can see doing this is that you want whatever the issue is to not stop execution. If you are going to do something like this, it's really crucial to make sure that you return something sensible that works for the caller. If the next thing that happens is that the calling code throws its own exception because e.g., None doesn't have an add method, you are at best just making things harder to troubleshoot. It could be a lot worse, however. A lot of serious bugs are due to returning nulls/None after catching an error. I think there are times that is makes sense to do this, but they are rare in my experience.
Allowing the raw exception to bubble out is the next least-worst option, IMO. This can be fine if you are building something small where it will be easy to find the what the problem is when things crash with a KeyError. In a situation where you are leveraging a lot of duck-typing, passing around function references, or using annotations, it can sometimes be difficult. For example, if you are using this code behind a web endpoint, what HTTP error code should you use when you catch a KeyError. 500 might be the right answer in most cases but there might be times you want to produce something else depending on where the key was not found.
That brings me to the last option which you don't mention: catch and raise a separate, more meaningful error. That allows you to distinguish between say, a KeyError thrown because the request was for something that isn't valid and a KeyError thrown because of a bad configuration.
Neither is pythonic. Pythonic code would be:
my_dict = {}
def fetch_value(key):
return my_dict[key]
val = fetch_value('my_key')
Remember, simple is better than complex and flat is better than nested. Since your except-block does not handle the exception in any meaningful way, it is better to just let it bubble up the call stack and terminate the program.
But in your code the error is ignored and it implicitly returns None if the key is not found. If this is what you want, then it can be done simpler with the get() method:
def fetch_value(key):
return my_dict.get(key)
"Handling" an error by just logging a message and then continuing as if nothing happened, is a terrible antipattern from the Java world which has no place in Python. Exceptions should only be caught if they can be meaningfully handled.
I am writing a python script to interact with an instrument. The instrument comes with a python library that I am using in my script.
I am not sure what might be the best practice for using try/except blocks in Python.
Approach 1:
try: some_command_1 except Exception as e: logger.exception(e) try: some_command_2 except Exception as e: logger.exception(e) . . . try: some_command_n except Exception as e: logger.exception(e)
Approach 2:
def main():
command_1()
command_2()
command_n()
if __name__ == "__main__":
try:
main()
except Exception as e:
logger.exception(e)When there is an error that raises to a level of an exception, I don't want my script to just catch the exception and move on to the next step.
The step where this error could have occurred might be critical that it is not necessary to proceed with the execution of the remainder of the script.
I am thinking that Approach 2 might be the best approach for my problem. But is it a good practice to do it this way?
The type of error that raises to the level of exception include: Instrument has a problem that it doesn't want to execute the command, lost communications etc.
No, you cannot do that. That's just the way Python has its syntax. Once you exit a try-block because of an exception, there is no way back in.
What about a for-loop though?
funcs = do_smth1, do_smth2
for func in funcs:
try:
func()
except Exception:
pass # or you could use 'continue'
Note however that it is considered a bad practice to have a bare except. You should catch for a specific exception instead. I captured for Exception because that's as good as I can do without knowing what exceptions the methods might throw.
While the other answers and the accepted one are correct and should be followed in real code, just for completeness and humor, you can try the fuckitpy ( https://github.com/ajalt/fuckitpy ) module.
Your code can be changed to the following:
@fuckitpy
def myfunc():
do_smth1()
do_smth2()
Then calling myfunc() would call do_smth2() even if there is an exception in do_smth1())
Note: Please do not try it in any real code, it is blasphemy