A question and answer about Python exception handling from the StackOverflow.
Question: Why is "Except:pass" a bad programming habit?
I often see people commenting on the use of Except:pass in StackOverflow, and they all mention that this is a bad Python programming habit that should be avoided. But I want to know why? Sometimes I don't care about the mistakes I make, but I just want my program to go on. Just like this:
Try:
something
except:
Pass
Why is it so bad to use Except:pass? What is the reason behind this, is it because I will let go of some mistakes that should be handled? Or do I catch all types of bugs?
Best Answer:
As you can guess, there are two bad places to do this. First, any type of error is caught because no exception type is specified. Second, capturing an error simply allows it to pass rather than take the necessary processing action.
My next explanation may be a bit long, so I'll focus on the following:
1. Do not use any type of error as a capture object. You must be clear about the types of errors you want to capture and specify that they are captured only.
2. Do not attempt to simply perfunctory the error handling action. Unless this is done for a purpose, it is usually not very good.
So then let's go a little deeper:
Do not use any exception as a capture target
When you use an exception to catch a block of statements somewhere in your code, you usually know that the place might throw an exception, and you know what kind of problem this place might have and then throw the exception, and once the exception is thrown, you'll catch the exception and get the program back on track. This means that you must be prepared for this anomaly and be able to take steps to deal with it when it happens.
For example, you would need a user to enter a number and use the Int () function to convert the string entered by the user to an integer type, and you would think that if the input string is not a number, then a value error (VALUEERROR) will occur. If there is a real mistake, then you can simply let the user re-enter to get the program back on track, so capturing the value error and prompting the user to re-enter is a more reasonable processing strategy. As an example, if you want to read the configuration information from a file, it just happens that the file does not exist. So because this is a configuration file, if it doesn't exist you will return some default configuration options, so this file is not necessary. In this example, the capture file does not find the error (FILENOTFOUNDERROR) and returning the default configuration item is a more appropriate processing strategy. As you can see from the above two examples, we are all waiting to catch a specific error and have a specific handling strategy for each of these errors.
However, if we catch all the exceptions here, the processing policies that are prepared for a particular exception are invalidated by unusual types of exceptions, which can disrupt the normal program flow and cannot be recovered.
Let's just take that example of a configuration file. The normal processing policy is that if the file does not exist, we will use the default configuration item and may later decide whether or not to automatically save the current configuration item as a configuration file (so that the next file will definitely exist). Now let's assume we've caught a isadirectoryerror or permissionerror error, in which case we may not want the program to continue, we can still use the default configuration parameters, but then we can't save the file. It is also possible that the user wants to use a custom configuration item, so the default configuration item cannot be used. So we may need to immediately inform the user and stop the current program. It is also possible that we do not want to do so much in such a small piece of code, but let the application level of the part to care about it, so we may also let this error to the top layer, let the top-level business logic to deal with.
A simple example is also mentioned in the Python 2 idioms document documentation: If a simple spelling error occurs in our code, it causes a program error. In this case, because we catch all the exceptions, we will catch the name error (nameerrors) and the syntax error (syntaxerrors). Both are common mistakes and both do not want to appear in our final code. But because we catch anything, we will not be able to distinguish between the specific error types and debug when the anomaly occurs.
But there are dangerous anomalies that are not prepared in advance, such as system errors (SYSTEMERROR), which are so infrequent that we are not prepared at all; These exceptions often require more complex processing operations, which often may require us to stop our current work.
In any case, it is basically impossible to handle all exceptions through local code, so you should be targeted to deal with the specific exceptions that are prepared. Some people have suggested that the exception that is designed to terminate an application, such as a system exit (Systemexit) and a keyboard interrupt (keyboardinterrupt), should at least be clearly identified as a basic exception (Exception). But I want to say that it's not clear enough, and I personally think that only in one place can only catch exception or any type of exception, that is a separate, application-level exception capture, and the only task of the trap is to catch any possible unprepared for a slip through the exception. In this way, we can still retain information about unexpected exceptions as a basis for further code extensions (let's say if we can get the program back), so next time we will be able to explicitly specify this exception in the right place or instruct us to write test cases to ensure that the error does not recur (of course, All of this is going to go away when we're prepared for a particular anomaly, and the exception is not prepared.
In the logic of exception handling, don't do nothing.
When we explicitly catch a limited number of exceptions, we do not need to do any special processing. In this case, except Somespecificexception:pass can do so. But in most cases, we still need some code that is related to error recovery, such as repeated attempts and setting default values.
It also takes into account other situations, such as if our code structure has determined that we have to keep trying until we succeed in order to continue, then nothing is enough. Specifically, we need the user to enter a number because we know that the user may not be doing what we designed, so we'll put this part in a loop, like this:
Def askfornumber (): While
True:
try: return
int (input (' Please enter a number: ')
except valueerror:< C5/>pass
Because we will keep the user input until no exception is thrown, in which case we do not need to do any other special operations in the except block, which is enough. Of course, some people will say that you should at least let users get some error messages to find out why they are repeatedly asking for input here.
In other cases, the passing statement in the except block shows that we are not really ready for the exception. Unless there are some simple exceptions (such as a value error valueerror or a type error typeerror) We should all do some action, and the reason is obvious, to avoid simple passing. If there's really nothing to do (if you're sure), consider adding some explanatory annotations here; otherwise, extend the except block to add some restorative code.
Except:pass
The most intolerable is the combination of the two. This means that we voluntarily catch any anomalies (including those we are not prepared for) and turn a blind eye to them. You should at least record this error in the log and raise it up to terminate the current program (I don't believe that memoryerror your program is still working). Letting go of these exceptions will cause the program to run on the wrong track and lose the key error message so that the error is not easy to find, especially if you don't meet it yourself.
So the bottom line is to capture the specific exceptions that are prepared, and the other exceptions that occur are either waiting for you to fix the error or you can't handle it. It's OK to let go of certain anomalies when you really have nothing to do, otherwise you can only be thought of as doing or slacking off. You really ought to deal with these anomalies.