JPO : Webinar d'information sur nos formations → RDV mardi à 17h30.

Programación de API web en Python con Flask

Este artículo trata sobre la programación de API (Application Programming Interfaces) web en Python. Se trata de herramientas que permiten acceder a información y funciones a través de Internet. También encontrarás cómo conectar una API a una base de datos usando Python y cómo programar y documentar una API usando Python, flask, swagger y connexion. En este artículo veremos:

  1.     ¿Qué es una API?
  2.     ¿Cuándo se debe utilizar una API?
  3.     Terminología asociada a las API
  4.     Un primer ejemplo
  5.     Algunos principios de un buen diseño de API web
  6.     Ejemplos y documentación
  7.     Referencias bibliográficas

1. ¿Qué es una API?

Una API Web permite manipular información y funciones mediante programas informáticos a través de Internet.

Por ejemplo, con la API Web de Twitter se puede escribir un programa en un lenguaje como Python o Javascript que recoja metadatos sobre tuits.

De forma más general, en programación, el término API (abreviatura de Application Programming Interface) se refiere a una parte de un programa informático diseñada para ser utilizada o manipulada por otro programa, a diferencia de las interfaces, que están diseñadas para ser utilizadas o manipuladas por humanos.

Los programas informáticos a menudo necesitan comunicarse entre sí o con el sistema operativo subyacente, y las API son una forma de hacerlo.

En lo que sigue, sin embargo, nos limitaremos a las API web.

2. ¿Cuándo utilizar una API?

Cabe señalar que se puede proporcionar tanto un volcado de datos como una API; y son los usuarios quienes deben elegir lo que más les conviene.

Si tienes datos que deseas compartir con el mundo, crear una API Web es una forma de hacerlo.

Sin embargo, las API no siempre son la mejor forma de compartir datos con los usuarios.

Si el volumen de datos que quieres compartir es relativamente pequeño, es mejor ofrecer un volcado de datos en forma de archivo JSON, XML, CSV o Sqlite. En función de los recursos disponibles, este enfoque puede ser viable hasta un volumen de unos pocos gigabytes.

Por lo general, utilizamos una API Web cuando:

  • Nuestro conjunto de datos es voluminoso, por lo que una descarga a través de FTP resulta engorrosa o consume muchos recursos.
  • Los usuarios necesitan acceder a los datos en tiempo real, por ejemplo, para visualizarlos en un sitio web o como parte de una aplicación.
  • Nuestros datos se modifican o actualizan con frecuencia.
  • Los usuarios solo necesitan acceder a una parte de los datos cada vez.
  • Los usuarios necesitan realizar acciones distintas a la simple consulta de los datos, como por ejemplo contribuir, actualizar o borrar.

3. Terminología asociada a las API

HTTP (HyperText Transfer Protocol): es la principal forma de comunicar información en Internet. HTTP implementa una serie de «métodos» que especifican la dirección hacia la que deben viajar los datos y lo que debe hacerse con ellos. Los dos más comunes son GET, que recupera datos de un servidor, y POST, que envía nuevos datos a un servidor.

URL (Uniform Resource Locator): dirección de un recurso en la web, como http://www-facultesciences.univ-ubs.fr/fr. Una URL consta de un protocolo (http://), un dominio (www-facultesciences.univ-ubs.fr) y una ruta opcional (/es).

Describe la ubicación de un recurso específico, como una página web. En el ámbito de las API, los términos URL, request, URI y endpoint hacen referencia a ideas similares. A continuación, solo utilizaremos los términos URL y request (solicitud), para mayor claridad.

Para realizar una solicitud GET o seguir un enlace, solo se necesita un navegador web.

JSON (JavaScript Object Notation): es un formato de almacenamiento de datos basado en texto y diseñado para ser leído tanto por humanos como por máquinas. JSON es el formato más común para los datos recuperados por las API, el segundo más común es XML.

REST (REpresentational State Transfer): es una metodología que reúne las mejores prácticas en materia de diseño e implementación de API. Las API diseñadas según los principios de la metodología REST se denominan API REST. Sin embargo, hay mucho debate sobre el significado exacto del término. En adelante, nos referiremos a ellas simplemente como API web o API HTTP.

4. Un primer ejemplo

A continuación veremos cómo crear una API utilizando Python y el marco de trabajo Flask.

Nuestro ejemplo de API será un directorio de empleados de una empresa, que facilitará su nombre, apellidos, cargo y antigüedad.

Empezaremos usando Flask para crear una página web para nuestro sitio. Esto nos permitirá ver cómo funciona Flask. Una vez que tengamos una aplicación Flask pequeña y funcional en forma de página web, convertiremos el sitio en una API.

¿Por qué Flask? Python tiene varios frameworks para producir páginas web y API.

El más conocido es Django, que es muy completo, pero puede ser abrumador para usuarios inexpertos.

Las aplicaciones Flask se construyen a partir de frameworks muy sencillos y, por tanto, son más adecuadas para la creación de prototipos de API.

Empezamos creando un nuevo directorio en el ordenador, que servirá como directorio del proyecto y al que llamaremos projects.

Los archivos de nuestro proyecto se almacenarán en un subdirectorio de proyectos, llamado api.

A continuación lanzamos Spyder 3 o cualquier otro IDE e introducimos el siguiente código:

El programa se guarda con el nombre api.py en el directorio api creado anteriormente.

Para ejecutarlo, abrimos una ventana de línea de comandos desde este directorio e introducimos los siguientes comandos:

 $ export FLASK_APP = api.py

 $ export FLASK_ENV = development

 $ flask run

Alternativamente, se puede ejecutar el programa en Spyder o en cualquier otro IDE que se utilice.

La consola mostrará lo siguiente (entre otras salidas):

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Basta con introducir el enlace anterior en un navegador web para acceder a la aplicación.

Así que ya tienes una aplicación web funcionando.

Ahora echemos un vistazo a cómo funciona Flask.

Flask envía peticiones HTTP a funciones Python. En nuestro caso, hemos aplicado una ruta URL (‘/’) a una función: home.

Flask ejecuta el código de la función y muestra el resultado en el navegador. En nuestro ejemplo, el resultado es un código HTML de bienvenida al sitio que aloja nuestra API.

El proceso de aplicar URL a funciones se denomina enrutamiento (routing).

La instrucción:

@app.route(‘/’, methods=[‘GET’])

que aparece en el programa indica a Flask que la función home corresponde a la ruta /.

La lista de métodos (methods=[‘GET’]) es un argumento clave que indica a Flask qué tipo de peticiones HTTP están permitidas.

A continuación solo utilizaremos peticiones GET, pero muchas aplicaciones web utilizan tanto peticiones GET (para enviar datos desde la aplicación a los usuarios) como peticiones POST (para recibir datos de los usuarios).

Veamos el programa más de cerca.

import Flask: Esta instrucción se utiliza para importar la librería Flask, que está disponible por defecto en Anaconda.

app = flask.Flask(__name__): Crea el objeto de aplicación Flask, que contiene los datos de la aplicación y los métodos correspondientes a las acciones que se pueden realizar sobre el objeto. La última instrucción app.run( ) es un ejemplo de uso de un método.

app.config[«DEBUG» = True]: Lanza el depurador, que muestra un mensaje distinto de «Bad Gateway» si hay un error en la aplicación.

app.run( ): Permite ejecutar la aplicación.

Ahora, para crear la API, vamos a especificar nuestros datos en forma de lista de diccionarios Python.

Por ejemplo, vamos a proporcionar los datos de tres empleados de nuestra empresa. Cada diccionario contendrá el número de identificación del empleado, sus apellidos, su nombre, su cargo y su antigüedad.

También introduciremos una nueva función: una ruta que permita a los visitantes acceder a nuestros datos.

Así que sustituimos el código guardado en api.py por el siguiente código:

Ejecutamos el código en Spyder 3 y actualizamos la ventana del navegador, que nos da :

Directorio de Internet

Para acceder a todos los datos, basta con introducir la dirección: http://127.0.0.1:5000/api/v1/resources/employees/all

Utilizamos la función jsonify de Flask. Esta función convierte listas y diccionarios en formato JSON.

Utilizando la ruta que hemos creado, los datos de nuestros empleados se convierten de una lista de diccionarios al formato JSON, antes de proporcionárselos al usuario.

En esta fase, hemos creado una API funcional, aunque limitada.

En el estado actual de nuestra API, los usuarios solo pueden acceder a la totalidad de nuestros datos; no pueden especificar filtros para encontrar recursos específicos.

Aunque esto no es un problema con nuestros datos de prueba, que son pocos, se vuelve problemático a medida que se añaden más datos.

A continuación, vamos a introducir una función que permite a los usuarios filtrar los resultados devueltos mediante consultas más específicas.

El nuevo código es el siguiente:

Una vez introducido, guardado y ejecutado el código en Spyder 3, se pueden introducir las siguientes direcciones en el navegador:

127.0.0.1:5000/api/v1/resources/employees?id=0

127.0.0.1:5000/api/v1/resources/employees?id=1

127.0.0.1:5000/api/v1/resources/employees?id=2

127.0.0.1:5000/api/v1/resources/employees?id=3

Cada una de estas direcciones devuelve un resultado diferente, excepto la última, que devuelve una lista vacía, ya que no hay ningún identificador de empleado 3.

A continuación, vamos a ver en detalle nuestra nueva API.

Hemos creado una nueva función api_root, con la instrucción @app_route, aplicada a la ruta /api/v1/resources/employees.

Esto significa que la función se ejecuta en cuanto se accede a http://127.0.0.1:5000/api/v1/resources/employees.

Hay que tener en cuenta que acceder al enlace sin especificar un ID devuelve el mensaje de error especificado en el código: Error: No ID provided. Por favor, especifique un ID.

En nuestra función, hacemos dos cosas: primero examinamos la URL proporcionada para buscar un identificador y luego seleccionamos el libro que coincide con el identificador.

El identificador debe proporcionarse con la sintaxis ?id=0, por ejemplo.

Los datos que se pasan a la URL de esta forma se denominan parámetros de solicitud. Son una característica del protocolo HTTP.

La siguiente parte del código determina si existe un parámetro de solicitud del tipo ?id=0, y asigna el ID suministrado a una variable.

A continuación, se busca en el directorio de empleados, se identifica al empleado con el ID especificado y se añade a la lista devuelta como resultado.

Por último, la instrucción return jsonify(results) devuelve los resultados en formato JSON para su visualización en el navegador.

En esta etapa, hemos creado una API funcional. En las siguientes entradas, veremos cómo crear una API un poco más compleja, utilizando una base de datos. Sin embargo, los principios fundamentales y las instrucciones seguirán siendo los mismos.

5. Algunos principios de un buen diseño de API web

Dos aspectos de las buenas API son la usabilidad y la mantenibilidad. Tendremos en cuenta estos requisitos a la hora de programar API en Python.

La metodología de diseño de API más utilizada se llama REST.

El aspecto más importante de REST es que se basa en cuatro métodos definidos por el protocolo HTTP: GET, POST, PUT y DELETE. Estos corresponden a las cuatro operaciones estándar que se realizan en una base de datos: READ, CREATE, UPDATE y DELETE.

En el resto del artículo examinaremos las solicitudes GET, que se utilizan para leer de una base de datos.

Las solicitudes HTTP juegan un papel esencial en la metodología REST, con muchos principios de diseño que giran en torno a cómo deben formatearse las solicitudes.

Ya hemos creado una solicitud HTTP que nos devuelve todo nuestro catálogo.

Empecemos con una solicitud mal diseñada:

http://api.example.com/getemployee/10

Esta solicitud plantea varios problemas: el primero es semántico; en una API REST, los verbos típicos son GET, POST, PUT y DELETE, y vienen determinados por el método de solicitud y no por la URL de la solicitud. Esto significa que la palabra «get» no debería aparecer en la solicitud, ya que «get» está implícito por el hecho de que se está utilizando una solicitud HTTP GET.

Además, las colecciones de recursos, como empleados o usuarios, deben designarse con nombres en plural.

Esto facilita la identificación si la API se refiere a una colección de empleados (employees) o a un empleado en particular (employee).

Teniendo en cuenta estas observaciones, la nueva forma de nuestra solicitud es la siguiente:

http://api.example.com/employees/10

La solicitud anterior utiliza parte de la ruta para proporcionar el identificador.

Aunque este enfoque se utiliza en la práctica, es demasiado rígido: con las URL construidas de este modo, solo se puede filtrar por un campo cada vez.

Los parámetros de consulta pueden utilizarse para filtrar por varios campos de la base de datos y para especificar datos adicionales, como un formato de respuesta:

http://api.example.com/employees?apellidos=Durand&nombre=Elodie&output=xml

A la hora de desarrollar la estructura de las solicitudes enviadas a una API, también es conveniente planificar futuros desarrollos.

Aunque la versión actual de la API solo proporciona información sobre un tipo de recurso (employees), tiene sentido prever incorporar otros recursos o funcionalidades a nuestra API, lo que da:

http://api.example.com/resources/employees?id=10

Especificar un segmento «recursos» en la ruta, permite ofrecer a los usuarios la opción de acceder a todos los recursos disponibles, con solicitudes como:

https://api.example.com/v1/resources/images?id=10

https://api.example.com/v1/resources/all

Otra forma de contemplar futuros desarrollos de la API es añadir un número de versión a la ruta.

Esto permite mantener el acceso a la antigua API si se desarrolla una nueva versión, como la v2, de la API.

Esto permite que las aplicaciones y scripts diseñados con la primera versión de la API sigan funcionando después de la actualización.

Por último, una solicitud bien diseñada, en el marco de la metodología REST, tiene la siguiente forma:

https://api.example.com/v1/resources/employees?id=10

6. Ejemplos y documentación

Sin documentación, incluso la mejor API es inutilizable.

La documentación debe estar asociada a la API, que describe los recursos o funcionalidades disponibles a través de ella y proporciona ejemplos concretos de URL de solicitud y código.

Debe haber un párrafo para cada recurso en el que se describan los campos que pueden solicitarse, como el título y el ID.

Cada párrafo debe proporcionar un ejemplo de solicitud HTTP o un bloque de código.

Una práctica común en la documentación de API es anotar el código, y las anotaciones se pueden agrupar automáticamente en una documentación utilizando herramientas como Doxygen o Sphinx.

Estas herramientas generan documentación a partir de «docstrings», es decir, cadenas de caracteres que documentan funciones.

Aunque este tipo de documentación tiene un valor incalculable, no debemos detenernos ahí. Hay que ponerse en la piel de un usuario y ofrecerle ejemplos concretos de uso.

Lo ideal es disponer de tres tipos de documentación:

  • una referencia que detalle cada ruta y su comportamiento;
  • una guía que explique la referencia en de manera sencilla;
  • uno o dos tutoriales que expliquen detalladamente cada paso.

Para un ejemplo de documentación de API, consulta la API de Colecciones Digitales de la Biblioteca Pública de Nueva York, que constituye un buen estándar.

Otro ejemplo más extenso es la MediaWiki Action API, que proporciona documentación que permite a los usuarios enviar solicitudes parciales a la API.

Otros ejemplos de documentación de API son la API del Banco Mundial y la API de European Pro.

7. Referencias

¿No está disponible?

Déjenos su dirección de correo electrónico para que podamos enviarle los nuevos artículos cuando se publiquen.