Simplified Exception Identification in Python

Using functions and exception pattern dictionaries to simplify error recovery.
A Dictionary of Known Exception Patterns

The name of the exception class is not enough to generalize properly the handling of exceptions. As an example, the socket module generates many different exceptions for various conditions, and they all are named "error". What makes each condition distinct lies in the exceptions details. The tuple ('error', (111, 'Connection refused') ) is different from ('error', (32, 'Broken pipe') ).

So what we will do instead is create a dictionary whose keys define exact exceptions. Each of those keys will have a simple integer value that reduces multiple cases to a smaller number. The following dictionary is not complete, but it gives a good idea of how to proceed and build a larger one.

     EXC_DISCONNECT  = 1
     EXC_SERVER_NOT_AVAILABLE = 2
     ExcDiagDict = {
        # another famous OS:
        repr( ('error', (10061, 'Connection refused') ) ) :
     EXC_SERVER_NOT_AVAILABLE,
        # Linux 2.4:
        repr( ('error', (111, 'Connection refused') ) )   :
     EXC_SERVER_NOT_AVAILABLE,
        repr( ('error', (32, 'Broken pipe') ) )           : EXC_DISCONNECT,
        repr( ('error', (107, 'Transport endpoint is not connected') ) ) :
     EXC_DISCONNECT,
      }

In this exception "diagnosis" dictionary, a repr() surrounds each of the tuples that makes up a key. In this example, strings are the only practical way to retrieve the expected results from the dictionary. Using a tuple directly does not work--no match would ever be found, unless the exact same instances of objects and tuples were used in the look-up. String keys are used because they are less restrictive and work according to their lexical values.

In the dictionary as it is initialized above, we have two keys associated with the constant EXC_SERVER_NOT_AVAILABLE. Each of these two keys represents an ('error', (number, 'Connection refused')) exception, but the value of the number varies according to the operating system being used. The last two keys are two completely different exceptions that can happen under Linux, but they basically indicate the same event--a disconnect on a socket. The dictionary can be expanded to include similar exception patterns on more platforms, as well as more exception patterns related to one or more basic events.

If you take the previous import statements, the previous definition of the function formatExceptionInfo() and the dictionary above, you can append the following code:

     def getDiagnosisFromExcInfo(excInfoTuple):
         try:
           excPattern = (excInfoTuple[0], excInfoTuple[1])
           return ExcDiagDict[ repr(excPattern) ]
         except KeyError:
           return None
         except:
           return None    # maybe was not tuple?
     from socket import *
     try:
         s = socket(AF_INET, SOCK_STREAM)
         s.connect( ("127.0.0.1", 7788) )
         s.close()
     except:
         exInfo = formatExceptionInfo()
         diag = getDiagnosisFromExcInfo(exInfo)
         print "diag:", diag, "exc:", exInfo

When you run that code, the following should be returned:

     diag: 2 exc: ('error', (111, 'Connection refused'), ['File "<stdin>",
     line 3, in ?\n', ...]

The "2" is the value of the constant EXC_SERVER_NOT_AVAILABLE, which is indeed the constant associated with the Connection refused exception pattern in the sample dictionary. From experience, it is safe to say that error recovery code that uses formatExceptionInfo() and getDiagnosisFromExcInfo() is much simpler and, therefore, more reliable.

Conclusion

With the function formatExceptionInfo(), we have found a way to learn important information about any exception from the Python sys.exc_info() function. Also, the exception patterns dictionary makes it possible to simplify the identification of various exceptions, even if they differ from one OS to another or if they actually refer to the same event.

Jean-Francois Touchette has been developing software for 20 years. He has written several gateways and servers with various protocols since 1985. He has been using C and UNIX since that time. When Python is suitable, he prefers it.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Re: Simplified Exception Identification in Python

Anonymous's picture

Dude, ever hear of errno?

errno is not thread safe

JFT's picture

Only luck would prevent another thread from modifying the value of errno between the time when the first thread does something which sets the value of errno and the time when this first thread checks its value.
And...
Of course, in production environments, Murphy's laws apply fully and that nasty scenario would hit you at the worst possible moment. ;)

Re: Simplified Exception Identification in Python

Anonymous's picture

The same as the first comment, thanks, exactly what I needed to know, I was having trouble getting the trace back from errors in a threaded program

Re: Simplified Exception Identification in Python

Anonymous's picture

[to author:] Dude, ever hear of errno?

Re: Simplified Exception Identification in Python

Anonymous's picture

Thanks man, this was exactly the code I was looking for.

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix