Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling a Python exception that occurs within an except clause

I have some code in a Python except clause that is intended to do some logging, but the logging code might itself cause an exception. In my case, I'd like to just ignore any second exception that might occur, and raise the original exception. Here is a very simplified example:

try:     a = this_variable_doesnt_exist except:     try:         1/0     except:         pass     raise 

Running the above code, I hope to get:

NameError: name 'this_variable_doesnt_exist' is not defined 

but instead, in Python 2.x, I get:

ZeroDivisionError: integer division or modulo by zero 

I've discovered that in Python 3.x, it does what I want.

I couldn't find much commentary on this in the Python 2.x docs (unless I missed it). Can I achieve this in 2.x?

like image 475
Craig McQueen Avatar asked Jan 21 '10 02:01

Craig McQueen


People also ask

How do you handle exceptions in except Python?

The try and except Block: Handling Exceptions. The try and except block in Python is used to catch and handle exceptions. Python executes code following the try statement as a “normal” part of the program. The code that follows the except statement is the program's response to any exceptions in the preceding try clause ...

How do you use exception object with except statement?

If you write the code to handle a single exception, you can have a variable follow the name of the exception in the except statement. If you are trapping multiple exceptions, you can have a variable follow the tuple of the exception.

How do you use except clause in Python?

The try block lets you test a block of code for errors. The except block lets you handle the error. The else block lets you execute code when there is no error. The finally block lets you execute code, regardless of the result of the try- and except blocks.

How do you handle exceptions with try except finally in Python explain with coding snippets?

In Python, exceptions can be handled using a try statement. The critical operation which can raise an exception is placed inside the try clause. The code that handles the exceptions is written in the except clause. We can thus choose what operations to perform once we have caught the exception.


2 Answers

I believe what you're seeing is the result of exception chaining, which is a change in Python 3.

From the Motivation section of the PEP:

During the handling of one exception (exception A), it is possible that another exception (exception B) may occur. In today's Python (version 2.4), if this happens, exception B is propagated outward and exception A is lost. In order to debug the problem, it is useful to know about both exceptions. The __context__ attribute retains this information automatically.

The PEP then goes on to describe the new exception chaining (which is implemented in Py3k) in detail—it's an interesting read. I learned something new today.

like image 152
Alok Singhal Avatar answered Oct 13 '22 02:10

Alok Singhal


With abstraction:

def log_it():     try:         1 / 0     except:         pass  try:     this = that except:     log_it()     raise 

Does what you want in Python 2.5

Another way to do it is to store the exception in a variable, then re-raise it explicitly:

try:     this = that except NameError, e: # or NameError as e for Python 2.6     try:         1 / 0     except:         pass     raise e 

Note that you probably shouldn't just be using a bare except to catch everything that might come - it's usually best to catch the specific exceptions you expect to occur in case a drastic and fatal exception (like being out of memory) occurs.

like image 36
Chris Lutz Avatar answered Oct 13 '22 01:10

Chris Lutz