2015-06-23 15 views
5

Używam trochę usługi internetowej opartej na kolbie Pythona, w której chcę wykonać małe zapytanie MySQL. Kiedy otrzymam poprawne dane wejściowe dla mojego zapytania SQL, wszystko działa zgodnie z oczekiwaniami i otrzymuję właściwą wartość. Jednakże, jeśli wartość nie jest przechowywana w bazie danych otrzymuję TypeErrorObsługa błędów w Pythonie-MySQL

Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1836, in __call__ 
    return self.wsgi_app(environ, start_response) 
    File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1820, in wsgi_app 
    response = self.make_response(self.handle_exception(e)) 
    File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1403, in handle_exception 
    reraise(exc_type, exc_value, tb) 
    File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1817, in wsgi_app 
    response = self.full_dispatch_request() 
    File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1478, in full_dispatch_request 
    response = self.make_response(rv) 
    File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1566, in make_response 
    raise ValueError('View function did not return a response') 
ValueError: View function did not return a response 

próbowałem dopasować się do błędu obchodzenia się i użyć tego kodu do mojego projektu, ale wydaje się, że to nie działa prawidłowo.

#!/usr/bin/python 

from flask import Flask, request 
import MySQLdb 

import json 

app = Flask(__name__) 


@app.route("/get_user", methods=["POST"]) 
def get_user(): 
    data = json.loads(request.data) 
    email = data["email"] 

    sql = "SELECT userid FROM oc_preferences WHERE configkey='email' AND configvalue LIKE '" + email + "%';"; 

    conn = MySQLdb.connect(host="localhost", 
          user="root", 
          passwd="ubuntu", 
          db="owncloud", 
          port=3306) 
    curs = conn.cursor() 

    try: 
     curs.execute(sql) 
     user = curs.fetchone()[0] 
     return user 
    except MySQLdb.Error, e: 
     try: 
      print "MySQL Error [%d]: %s" % (e.args[0], e.args[1]) 
      return None 
     except IndexError: 
      print "MySQL Error: %s" % str(e) 
      return None 
    except TypeError, e: 
     print(e) 
     return None 
    except ValueError, e: 
     print(e) 
     return None 
    finally: 
     curs.close() 
     conn.close() 

if __name__ == "__main__": 
    app.run(host="0.0.0.0", port=5000, debug=True) 

Zasadniczo Chcę tylko zwrócić wartość, gdy wszystko działa poprawnie i chcę powrócić nic, jeśli nie jest najlepiej z komunikatem o błędzie na moim serwerze. Jak mogę prawidłowo obsługiwać błędy?

EDIT Zaktualizowany aktualny kod + komunikat o błędzie.

+0

** z wyjątkiem TypeError, e: ** nie działa poprawnie? –

+0

@ kuket15 próbowałem tego również wcześniej. Otrzymano ** ValueError ** po tym: D I kiedy użyłem ** oprócz ValueError, e: ** po tym, nadal otrzymałem ** ValueError **. Zmieniłem moje pytanie teraz, więc możesz zobaczyć mój aktualny status –

+1

Jeśli jest to kolba wychwytująca wyjątek, funkcja ValueError ("Funkcja widoku nie powróciła ...") może być podnoszona przez istniejący Brak powrotu. Spróbuj manekina- ciąg w zamian lub z wyjątkiem ValueError: zamiast tego przekazać do porównania? Lub przeczytaj kod pułapki wyjątku w kolbie, byłby moją sugestią; aby dowiedzieć się, jak wobt spowodować podniesienie kolby. Może tu masz związane ręce. –

Odpowiedz

9

Pierwszy punkt: w bloku try/except znajduje się zbyt wiele kodu. Lepiej użyć wyraźną try/oczekiwać bloków, kiedy masz dwa oświadczenia (lub dwie grupy sprawozdania), które mogą budzić różne błędy:

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() 

Czy teraz naprawdę muszę złapać TypeError tutaj? Jeśli czytasz w punkcie zwrotnym, zauważysz, że Twój błąd pochodzi z wywołania __getitem__() na None (nb: __getitem__() jest implementacją dla operatora indeksowania []), co oznacza, że ​​jeśli nie masz pasujących wierszy cursor.fetchone() zwraca None, więc możesz po prostu przetestować powrót 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() 

teraz czy naprawdę trzeba złapać błędów MySQL tutaj? Twoje zapytanie ma być dobrze przetestowane i jest tylko operacją odczytu, więc nie powinno się zawieszać - więc jeśli coś tu nie działa, to oczywiście masz większy problem i nie chcesz go ukrywać pod dywanem. IOW: albo zalogować wyjątki (przy użyciu standardowego logging pakiet i logger.exception()) i ponownie podnieść je lub prościej niech propagują (i ostatecznie mają wyższy poziom componant zająć zalogowaniu nieobsłużonych wyjątków):

try: 
    curs.execute(sql) 
    row = curs.fetchone() 
    if row: 
     return row[0] 
    return None 

finally: 
    conn.close() 

I wreszcie: sposób budowania zapytania sql to utterly unsafe. Zamiast tego użyj symboli zastępczych sql:

q = "%s%%" % data["email"].strip() 
sql = "select userid from oc_preferences where configkey='email' and configvalue like %s" 
cursor.execute(sql, [q,])