Creé una aplicación de matraz simple y estoy leyendo la respuesta de python como:
response = requests.post(url,data=json.dumps(data), headers=headers ) data = json.loads(response.text)Ahora mi problema es que, bajo ciertas condiciones, quiero devolver una respuesta de 400 o 500 mensajes. Hasta ahora lo estoy haciendo así:
abort(400, 'Record not found') #or abort(500, 'Some error...')Esto imprime el mensaje en la terminal:
Pero en la respuesta de la API seguí recibiendo una respuesta de error 500:
La estructura del código es la siguiente:
|--my_app |--server.py |--main.py |--swagger.yml Donde server.py tiene este código:
from flask import render_template import connexion # Create the application instance app = connexion.App(__name__, specification_dir="./") # read the swagger.yml file to configure the endpoints app.add_api("swagger.yml") # Create a URL route in our application for "/" @app.route("/") def home(): """ This function just responds to the browser URL localhost:5000/ :return: the rendered template "home.html" """ return render_template("home.html") if __name__ == "__main__": app.run(host="0.0.0.0", port="33") Y main.py tiene todas las funciones que estoy usando para los puntos finales de la API.
P.EJ:
def my_funct(): abort(400, 'Record not found') Cuando se llama a my_funct , obtengo el Record not found impreso en el terminal, pero no en la respuesta de la propia API, donde siempre recibo el mensaje de error 500.
Puede devolver una tupla con el segundo elemento como estado (400 o 500).
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Record not found", 400 if __name__ == '__main__': app.run()Ejemplo de llamada a la API desde python:
import requests response = requests.get('http://127.0.0.1:5000/') response.text # 'This is a bad request!' response.status_code # 400Me gusta usar la clase flask.Response :
from flask import Response @app.route("/") def index(): return Response( "The response body goes here", status=400, ) flask.abort es un envoltorio alrededor werkzeug.exceptions.abort que en realidad es solo un método auxiliar para facilitar la generación de excepciones HTTP. Eso está bien en la mayoría de los casos, pero para las API tranquilas, creo que puede ser mejor ser explícito con las respuestas de retorno.
Aquí hay algunos fragmentos de una aplicación de Flask que escribí hace años. Tiene un ejemplo de una respuesta 400.
import werkzeug from flask import Flask, Response, json from flask_restplus import reqparse, Api, Resource, abort from flask_restful import request from flask_cors import CORS app = Flask(__name__) CORS(app) api = Api(app) parser = reqparse.RequestParser() parser.add_argument('address_to_score', type=werkzeug.datastructures.FileStorage, location='files') class MissingColumnException(Exception): pass class InvalidDateFormatException(Exception): pass @api.route('/project') class Project(Resource): @api.expect(parser) @api.response(200, 'Success') @api.response(400, 'Validation Error') def post(self): """ Takes in an excel file of addresses and outputs a JSON with scores and rankings. """ try: df, input_trees, needed_zones = data.parse_incoming_file(request) except MissingColumnException as e: abort(400, 'Excel File Missing Mandatory Column(s):', columns=str(e)) except Exception as e: abort(400, str(e)) project_trees = data.load_needed_trees(needed_zones, settings['directories']['current_tree_folder']) df = data.multiprocess_query(df, input_trees, project_trees) df = data.score_locations(df) df = data.rank_locations(df) df = data.replace_null(df) output_file = df.to_dict('index') resp = Response(json.dumps(output_file), mimetype='application/json') resp.status_code = 200 return resp @api.route('/project/health') class ProjectHealth(Resource): @api.response(200, 'Success') def get(self): """ Returns the status of the server if it's still running. """ resp = Response(json.dumps('OK'), mimetype='application/json') resp.status_code = 200 return respTienes una variedad de opciones:
Lo más básico:
@app.route('/') def index(): return "Record not found", 400Si desea acceder a los encabezados, puede tomar el objeto de respuesta:
@app.route('/') def index(): resp = make_response("Record not found", 400) resp.headers['X-Something'] = 'A value' return respO puede hacerlo más explícito, y no solo devolver un número, sino devolver un objeto de código de estado
from flask_api import status @app.route('/') def index(): return "Record not found", status.HTTP_400_BAD_REQUEST Puede leer más sobre los dos primeros aquí: Acerca de las respuestas (inicio rápido de Flask)
Y el tercero aquí: Códigos de estado (Guía de Flask API)
Creo que estás usando la función abort() correctamente. Sospecho que el problema aquí es que un controlador de errores detecta el error 400 y luego falla, lo que provoca el error 500. Consulte aquí para obtener más información sobre el manejo de errores de matraz.
Como ejemplo, lo siguiente cambiaría un error 400 a 500:
@app.errorhandler(400) def handle_400_error(e): raise Exception("Unhandled Exception") Si no está manejando ningún error, podría provenir del marco de connexion , aunque no estoy familiarizado con este marco.