hcvst
hcvst

Reputation: 2915

Python try except finally

It looks like I don't quite have the hang of Exception handling yet. I'm at a loss :( The following code sometimes returns this error:

File "applications/pingback/modules/plugin_h_pingback.py", line 190, in ping
    db(table.id==id_).update(status=status)
UnboundLocalError: local variable 'status' referenced before assignment

I would expect status to always have been assigned a value. Could it be that some other exception is thrown (perhaps in the inner try) and the finally obscures it?

...
try:
    server_url = self._get_pingback_server(target)
except PingbackClientError, e:
    status = e.message
else:
    try:
        server = xmlrpclib.ServerProxy(server_url)
        status = server.pingback.ping(self.source, target)
    except xmlrpclib.Fault, e:
        status = e
finally:
    db(table.id==id_).update(status=status) # <-- UnboundLocalError
...

Thanks, HC

Upvotes: 4

Views: 6526

Answers (2)

Mark Byers
Mark Byers

Reputation: 838706

Your code doesn't always assign something to status. I can see a few ways that status might not be assigned and I've highlighted them below:

try:
    server_url = self._get_pingback_server(target)
except PingbackClientError, e:
    # If evaluating `e.message` raises an exception then status is not set.
    status = e.message  # <--- here
else:
    try:
        # If either of these two lines fails with something other than
        # xmlrcplib.Fault, then status is not set.
        server = xmlrpclib.ServerProxy(server_url)             # <--- here
        status = server.pingback.ping(self.source, target)     # <--- here
    # If xmlrpclib.Fault is not defined status is not set.
    except xmlrpclib.Fault, e:                                 # <--- here
        status = e
finally:
    db(table.id==id_).update(status=status)

I suspect that the most likely place for the error is in the inner try block where you are only catching xmlrpclib.Fault and not other types of exceptions.

Upvotes: 10

Inca
Inca

Reputation: 1911

As a simple solution, I'd initialize status outside any blocks:

status = None
try: 
    # etc

Then status will always be bound. That will not solve the problem of any unhandled exception, but it will solve the UnboundLocalError.

(Also, in the first block you assing status with e.message, in the following block, you just use the complete error e, not just the message.)

Upvotes: 3

Related Questions