Sanic Web Framework: Un Tutorial Completo
Introducción
Sanic es un framework web de Python de código abierto que se construye sobre uvloop, una biblioteca de redes asíncronas de alta velocidad. Está diseñado para ser ligero y eficiente, lo que lo convierte en una excelente opción para desarrollar aplicaciones web de alto rendimiento. Sanic aprovecha la sintaxis async y await de Python para manejar las solicitudes de forma asíncrona, lo que le permite manejar un gran número de solicitudes concurrentes con facilidad.
Historia
Sanic fue lanzado por primera vez en 2016 por la comunidad de Sanic. Se inspiró en el framework web Flask y se creó para abordar las limitaciones de Flask en términos de rendimiento y escalabilidad. Sanic rápidamente ganó popularidad entre los desarrolladores debido a su velocidad y simplicidad, y desde entonces se ha convertido en uno de los frameworks web más utilizados en el ecosistema de Python.
Características
Sanic viene con una amplia gama de características que lo convierten en una herramienta poderosa para construir aplicaciones web. Algunas de las características clave de Sanic incluyen:
Manejo de solicitudes asincrónico: Sanic utiliza la sintaxis async y await de Python para manejar las solicitudes de forma asíncrona. Esto significa que se pueden procesar múltiples solicitudes de forma concurrente, lo que resulta en un mejor rendimiento y escalabilidad.
Ejecución rápida: Sanic se construye sobre uvloop, que es una biblioteca de redes asíncronas de alta velocidad. Esto permite que Sanic maneje un gran número de solicitudes de manera rápida y eficiente.
Enrutamiento: Sanic proporciona una forma sencilla e intuitiva de definir rutas de URL y vincularlas a funciones de controlador específicas. Esto facilita la creación de APIs RESTful y el manejo de diferentes tipos de solicitudes HTTP.
from sanic import Sanic
from sanic.response import text
app = Sanic()
@app.route('/')
async def hello(request):
return text('¡Hola, Sanic!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)En el fragmento de código anterior, definimos una ruta para la URL raíz ("/") y la vinculamos a la función de controlador
hello. Cuando se realiza una solicitud a la URL raíz, se ejecuta la funciónhelloy devuelve la respuesta "¡Hola, Sanic!".Soporte para middleware: Sanic te permite definir funciones de middleware que pueden interceptar y modificar tanto las solicitudes entrantes como las respuestas salientes. Esto es útil para tareas como la autenticación, el registro de solicitudes, el manejo de errores, etc.
from sanic import Sanic
from sanic.response import text
app = Sanic()
async def middleware_personalizado(request):
print('Antes de la solicitud')
response = await request.next()
print('Después de la respuesta')
return response
app.middleware(middleware_personalizado)
@app.route('/')
async def hello(request):
return text('¡Hola, Sanic!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)En el ejemplo anterior, definimos una función de middleware personalizado
middleware_personalizadoque imprime un mensaje antes de que se procese la solicitud y después de que se envíe la respuesta. El decoradormiddlewarese utiliza para registrar esta función de middleware en la aplicación de Sanic.Soporte para WebSocket: Sanic proporciona soporte incorporado para la comunicación mediante WebSocket, lo que te permite implementar fácilmente características en tiempo real en tus aplicaciones web.
from sanic import Sanic
from sanic.websocket import WebSocketProtocol
app = Sanic()
@app.websocket('/ws')
async def websocket_handler(request, ws):
while True:
message = await ws.recv()
await ws.send('¡Dijiste: ' + message + '!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, protocol=WebSocketProtocol)En el ejemplo anterior, definimos una ruta de WebSocket ("/ws") y la vinculamos a la función
websocket_handler. La función recibe un objeto WebSocketws, que se puede utilizar para enviar y recibir mensajes.Renderizado de plantillas: Sanic admite varios motores de plantillas, como Jinja2 y Mako, lo que te permite generar fácilmente páginas HTML dinámicas.
from sanic import Sanic
from sanic.response import html
from jinja2 import Template
app = Sanic()
@app.route('/')
async def index(request):
template = Template('<h1>¡Hola, {{ name }}!</h1>')
rendered_template = template.render(name='Sanic')
return html(rendered_template)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)En el fragmento de código anterior, definimos una plantilla Jinja2 que muestra un saludo personalizado. La plantilla se renderiza con el nombre "Sanic" y se devuelve como una respuesta HTML.
Validación de solicitudes: Sanic proporciona una forma sencilla de validar las solicitudes entrantes utilizando parámetros de solicitud, encabezados y otros atributos.
from sanic import Sanic
from sanic.exceptions import InvalidUsage
from sanic.request import RequestParameters
app = Sanic()
@app.route('/')
async def hello(request):
name = request.args.get('name')
if not name:
raise InvalidUsage('Se requiere el nombre.')
return text('¡Hola, ' + name + '!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)En el ejemplo anterior, validamos la solicitud comprobando si el parámetro
nameestá presente. Si no se proporciona, se genera una excepción y se devuelve un mensaje de error.
Ejemplos
Aquí hay algunos ejemplos que demuestran el uso de Sanic:
Ejemplo básico de Hola Mundo:
from sanic import Sanic
from sanic.response import text
app = Sanic()
@app.route('/')
async def hello(request):
return text('¡Hola, Sanic!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)Salida:
¡Hola, Sanic!Manejo de solicitudes asincrónico:
from sanic import Sanic
from sanic.response import text
import asyncio
app = Sanic()
@app.route('/')
async def hello(request):
await asyncio.sleep(1) # Simulando una tarea asíncrona
return text('¡Hola, Sanic!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)Salida:
¡Hola, Sanic!Ejemplo de middleware:
from sanic import Sanic
from sanic.response import text
app = Sanic()
async def middleware_personalizado(request):
print('Antes de la solicitud')
response = await request.next()
print('Después de la respuesta')
return response
app.middleware(middleware_personalizado)
@app.route('/')
async def hello(request):
return text('¡Hola, Sanic!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)Salida:
Antes de la solicitud
Después de la respuestaEjemplo de WebSocket:
from sanic import Sanic
from sanic.websocket import WebSocketProtocol
app = Sanic()
@app.websocket('/ws')
async def websocket_handler(request, ws):
while True:
message = await ws.recv()
await ws.send('¡Dijiste: ' + message + '!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, protocol=WebSocketProtocol)Salida:
¡Dijiste: Hola!
¡Dijiste: Sanic!
Para obtener más información, puedes visitar el sitio web oficial de Sanic.