When python struggles: Attribute Errors

Cliff Wells LogiplexSoftware at earthlink.net
Tue Dec 17 12:44:28 EST 2002


On Tue, 2002-12-17 at 05:22, matt wrote:
> I have a problem where the code:
> 
> # ------ begin code ------
> class DBInitializer:
>     def init(self, db_name, host, user="", password=""):
>         # Connect to host
>         if not self.status("Connecting to host: %s..." % host, \
>                            self.connect(host, user, password)):
>             ...
>         self.cursor = self.db.cursor()
> 	...
> 
>     def connect(self, host, user, password):
>         try:
>             self.db = MySQLdb.connect(host, user, password)
>         ...
> # ------ end code ------
> 
> raises an Attribute Error.
> 
> I tried putting "self.db=None" just before the self.status call but
> this only raised another Attribute Error complaining that "None" has
> no attribute "cursor".
> 
> The problem is that I can't instantiate the result of
> MySQLdb.connect() without the possibility or raising an error which i
> intend to catch in the self.connect method.

And after catching the error, what do you plan to do then?  Use the
cursor as if nothing had gone wrong?  That is how it appears in the
above code.

Better would be to raise an exception in the class and let the calling
code deal with it, or if you are intent upon continuing, just put set
self.db = None in the exception handler in DBInitializer.connect and
test for it before using the cursor:

class DBInitializer:
    def init(self, db_name, host, user="", password=""):
        # Connect to host
        if not self.status("Connecting to host: %s..." % host, \
                           self.connect(host, user, password)):
        ...
        if self.db is not None:
            self.cursor = self.db.cursor()
        else:
            self.cursor = None
	...

    def connect(self, host, user, password):
        try:
            self.db = MySQLdb.connect(host, user, password)
        except SomeError:
            self.db = None

> It's frustrating because if i were using C++ i could simply type "db =
> (MySQLdb_Connection*)0;" (or whatever the connection object would be
> called).

And then you would call cursor = db.cursor?  Sounds fishy.  If an object
fails in its initialization, continuing as if nothing had gone wrong
seems like a bad idea.  If the "DBInitializer" object fails to
initialize, what good is it?

I'd write it as:

class DBInitializer:
    def init(self, db_name, host, user="", password=""):
        # Connect to host
        if not self.status("Connecting to host: %s..." % host, \
                           self.connect(host, user, password)):
        ...
        self.cursor = self.db.cursor()
	...

    def connect(self, host, user, password):
        self.db = MySQLdb.connect(host, user, password)

and then put the instantiation of DBInitializer in a try/except
statement in the calling code. 

Obviously at some point in the calling program you're going to have to
test to see if the connection is valid anyway, so I'm not sure what
you're hoping to achieve by delaying that test (except executing
unnecessary code).

-- 
Cliff Wells, Software Engineer
Logiplex Corporation (www.logiplex.net)
(503) 978-6726 x308  (800) 735-0555 x308





More information about the Python-list mailing list