Client 2 - Adding Error Checking

   

Client 2 ”Adding Error Checking

If you look back to line 7 of Listing 17.1, you'll notice that you call pgdb.connect() to connect to a PostgreSQL server. If anything goes wrong during this function call, Python will print a stack trace and abort the program.

If you want to intercept a connection error, you must wrap the call to pgdb.connect() in a try/except block. The Python DB-API specification defines a hierarchy of exception types that a conforming implementation may throw. The most general exception type is StandardError . All other DB-API exceptions are derived (directly or indirectly) from StandardError . You might think that to catch a connection failure, you can get away with catching StandardError exceptions. Let's try it to see what happens. (Warning: Your red herring alarm should be sounding about now.)

Listing 17.2 shows client2a.py . Call pgdb.connect() inside of a try/except block and catch any exceptions derived from StandardError (including StandardError ).

Listing 17.2 client2a.py
 1 #!/usr/bin/python  2 #  3 # Filename: client2a.py  4  5 import pgdb  6  7 try:  8     connection = pgdb.connect( database = "movies",  9                                user     = "bruce", 10                                password = "cows" ) 11     print connection 12 13 except StandardError, e: 14     print str( e ) 

Now, let's run this client to see what a nice error message might look like (note: I have not restarted my Postmaster since the previous example, so I expect an error here):

 $ chmod a+x client2a.py $ ./client2a.py Traceback (innermost last):   File "./client2a.py", line 10, in ?     password = "cows" )   File "/usr/lib/python1.5/site-packages/pgdb.py", line 376, in connect     user = dbuser, passwd = dbpasswd)     pg.error: could not connect to server: No such file or directory         Is the server running locally and accepting         connections on Unix domain socket "/tmp/.s.PGSQL.5432"? 

Hey, that's the same message you saw when client1.py failed. You are catching StandardError exceptions, so the only possible explanation is that pgdb.connect() is throwing some other type of exception. You can add a little more code to determine what kind of exception is being thrown (see Listing 17.3).

Listing 17.3 client2b.py
 1 #!/usr/bin/python  2 #  3 # Filename: client2b.py  4  5 import pgdb  6 import sys  7  8 try:  9     connection = pgdb.connect( database = "movies", 10                                user     = "bruce", 11                                password = "cows" ) 12     print connection 13 14 except StandardError, e: 15     print str( e ) 16 17 except: 18     exception = sys.exc_info() 19 20     print "Unexpected exception:" 21     print "  type : %s" % exception[0] 22     print "  value: %s" % exception[1] 

In client2b.py , you use an untyped except clause, so you can catch any exception thrown by pgdb.connect() . When you catch an exception that has not been derived from StandardError , you use the sys.exc_info() function to obtain information about the exception. sys.exc_info() returns a tuple with three values: exception[0] contains the name of the exception type, exception[1] contains the exception parameter (usually an error message), and exception[2] contains a traceback object. We print the exception type and parameter:

 $ ./client2b.py Unexpected exception:   type : _pg.error   value: could not connect to server: No such file or directory         Is the server running locally and accepting         connections on Unix domain socket "/tmp/.s.PGSQL.5432"? 

Looking at the results, you can see that pgdb.connect() throws an exception of type _pg.error . This seems to violate the Python DB-API specification and is most likely a bug. All other PostgreSQL/DB-API functions (other than pgdb.connect() )seem to throw the exceptions prescribed by DB-API.

The Python DB-API describes the exception types shown in Table 17.1.

Table 17.1. DB-API Exception Types

Exception Type

Derived From

Thrown By

Warning

StandardError

Not used

Error

StandardError

Not used

InterfaceError

Error

execute()

executemany()

DatabaseError

Error

execute()

executemany()

DataError

DatabaseError

Not used

OperationalError

DatabaseError

execute()

executemany()

commit()

rollback()

cursor()

connect()

IntegrityError

DatabaseError

Not used

InternalError

DatabaseError

Not used

ProgrammingError

DatabaseError

Not used

NotSupportedError

DatabaseError

Not used

The first column in Table 17.1 shows the name of each exception. The middle column shows the parent type for each exception. The final column shows the name of each PostgreSQL/DB-API function that throws the exception.

It's important to remember that the DB-API functions can throw exceptions other than the ones listed in Table 17.1 (syntax errors, invalid data type errors, and so on). It's usually a good idea to catch specific exceptions that you expect to see with a typed except clause and catch unexpected exceptions with an untyped except . That's what we've done in client2a.py . The first except (at line 14) catches exceptions derived from StandardError . The second, at line 17, catches all other exceptions.

Now, you have a client application that establishes a connection or reports an error if the connection attempt fails. It's time to do something a little more interesting.

   


PostgreSQL
PostgreSQL (2nd Edition)
ISBN: 0672327562
EAN: 2147483647
Year: 2005
Pages: 220
Authors: Korry Douglas

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net