Error handling in Python-MySQL
First point: you have too much code in your try/except block. Better to use distinct try/except blocks when you have two statements (or two groups of statements) that may raise different errors:
try:
try:
curs.execute(sql)
# NB : you won't get an IntegrityError when reading
except (MySQLdb.Error, MySQLdb.Warning) as e:
print(e)
return None
try:
user = curs.fetchone()[0]
return user
except TypeError as e:
print(e)
return None
finally:
conn.close()
Now do you really have to catch a TypeError here ? If you read at the traceback, you'll notice that your error comes from calling __getitem__()
on None
(nb : __getitem__()
is implementation for the subscript operator []
), which means that if you have no matching rows cursor.fetchone()
returns None
, so you can just test the return of currsor.fetchone()
:
try:
try:
curs.execute(sql)
# NB : you won't get an IntegrityError when reading
except (MySQLdb.Error, MySQLdb.Warning) as e:
print(e)
return None
row = curs.fetchone()
if row:
return row[0]
return None
finally:
conn.close()
Now do you really need to catch MySQL errors here ? Your query is supposed to be well tested and it's only a read operation so it should not crash - so if you have something going wrong here then you obviously have a bigger problem, and you don't want to hide it under the carpet. IOW: either log the exceptions (using the standard logging
package and logger.exception()
) and re-raise them or more simply let them propagate (and eventually have an higher level component take care of logging unhandled exceptions):
try:
curs.execute(sql)
row = curs.fetchone()
if row:
return row[0]
return None
finally:
conn.close()
And finally: the way you build your sql query is utterly unsafe. Use sql placeholders instead:
q = "%s%%" % data["email"].strip()
sql = "select userid from oc_preferences where configkey='email' and configvalue like %s"
cursor.execute(sql, [q,])
Oh and yes: wrt/ the "View function did not return a response" ValueError, it's because, well, your view returns None
in many places. A flask view is supposed to return something that can be used as a HTTP response, and None
is not a valid option here.