@ -197,7 +197,7 @@ Aquí algunas cosas envueltas en elementos HTML "abbr" (algunas son inventadas):
### El abbr da una frase completa y una explicación { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbrtitle="Mozilla Developer Network - Red de Desarrolladores de Mozilla: documentación para desarrolladores, escrita por la gente de Firefox">MDN</abbr>
* <abbrtitle="Input/Output - Entrada/Salida: lectura o escritura de disco, comunicaciones de red.">I/O</abbr>.
* <abbrtitle="Input/Output - I/O: lectura o escritura de disco, comunicaciones de red.">I/O</abbr>.
////
@ -464,7 +464,7 @@ Para instrucciones específicas del idioma, mira p. ej. la sección `### Heading
La operación de path equivalente en FastAPI podría verse como:
La *path operation* API equivalente de FastAPI podría verse como:
```Python hl_lines="1"
@app.get("/some/url")
@ -183,7 +183,7 @@ Pero la documentación todavía falta. Entonces APISpec fue creado.
Es un plug-in para muchos frameworks (y hay un plug-in para Starlette también).
La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja un path.
La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja una ruta.
Y genera esquemas OpenAPI.
@ -245,11 +245,11 @@ Logra algo algo similar a lo que se puede hacer con Flask-apispec.
Tiene un sistema de inyección de dependencias integrado, inspirado por Angular 2. Requiere pre-registrar los "inyectables" (como todos los otros sistemas de inyección de dependencias que conozco), por lo que añade a la verbosidad y repetición de código.
Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte editorial es bastante bueno.
Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte del editor es bastante bueno.
Pero como los datos de TypeScript no se preservan después de la compilación a JavaScript, no puede depender de los tipos para definir validación, serialización y documentación al mismo tiempo. Debido a esto y algunas decisiones de diseño, para obtener validación, serialización y generación automática del esquema, es necesario agregar decoradores en muchos lugares. Por lo tanto, se vuelve bastante verboso.
No puede manejar muy bien modelos anidados. Entonces, si el cuerpo JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente.
No puede manejar muy bien modelos anidados. Entonces, si el body JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente.
/// tip | Inspiró a **FastAPI** a
@ -311,11 +311,11 @@ Requiere configuraciones un poquito más verbosas. Y dado que se basa en WSGI (e
El sistema de inyección de dependencias requiere pre-registrar las dependencias y las dependencias se resuelven en base a los tipos declarados. Por lo tanto, no es posible declarar más de un "componente" que proporcione cierto tipo.
Los paths se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas.
Las rutas se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas.
/// tip | Inspiró a **FastAPI** a
Definir validaciones extra para tipos de datos usando el valor "default" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes.
Definir validaciones extra para tipos de datos usando el valor "por defecto" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes.
Esto en realidad inspiró la actualización de partes de Pydantic, para soportar el mismo estilo de declaración de validación (toda esta funcionalidad ya está disponible en Pydantic).
@ -433,7 +433,7 @@ Tiene:
* CORS, GZip, Archivos estáticos, Responses en streaming.
* Soporte para sesiones y cookies.
* Cobertura de tests del 100%.
* code base 100% tipada.
* codebase 100% con anotaciones de tipos.
* Pocas dependencias obligatorias.
Starlette es actualmente el framework de Python más rápido probado. Solo superado por Uvicorn, que no es un framework, sino un servidor.
@ -89,7 +89,7 @@ Como el tiempo de ejecución se consume principalmente esperando operaciones de
Se llama "asíncrono" porque la computadora / programa no tiene que estar "sincronizado" con la tarea lenta, esperando el momento exacto en que la tarea termine, sin hacer nada, para poder tomar el resultado de la tarea y continuar el trabajo.
En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poco en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos.
En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poquito en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos.
Para el "sincrónico" (contrario al "asíncrono") comúnmente también usan el término "secuencial", porque la computadora / programa sigue todos los pasos en secuencia antes de cambiar a una tarea diferente, incluso si esos pasos implican esperar.
@ -151,7 +151,7 @@ Imagina que eres la computadora / programa 🤖 en esa historia.
Mientras estás en la fila, estás inactivo 😴, esperando tu turno, sin hacer nada muy "productivo". Pero la fila es rápida porque el cajero solo está tomando los pedidos (no preparándolos), así que está bien.
Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, verificas que das el billete o tarjeta correctos, verificas que te cobren correctamente, verificas que el pedido tenga los artículos correctos, etc.
Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, revisas que das el billete o tarjeta correctos, revisas que te cobren correctamente, revisas que el pedido tenga los artículos correctos, etc.
Pero luego, aunque todavía no tienes tus hamburguesas, tu trabajo con el cajero está "en pausa" ⏸, porque tienes que esperar 🕙 a que tus hamburguesas estén listas.
@ -387,7 +387,7 @@ En versiones previas de NodeJS / JavaScript en el Navegador, habrías usado "cal
## Coroutines { #coroutines }
**Coroutines** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él.
**Coroutine** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él.
Pero toda esta funcionalidad de usar código asíncrono con `async` y `await` a menudo se resume como utilizar "coroutines". Es comparable a la funcionalidad clave principal de Go, las "Goroutines".
@ -417,7 +417,7 @@ Si tienes bastante conocimiento técnico (coroutines, hilos, bloqueo, etc.) y ti
Cuando declaras una *path operation function* con `def` normal en lugar de `async def`, se ejecuta en un threadpool externo que luego es esperado, en lugar de ser llamado directamente (ya que bloquearía el servidor).
Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir funciones de *path operation* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice <abbrtitle="Input/Output - Entrada/Salida: lectura o escritura en disco, comunicaciones de red.">I/O</abbr> de bloqueo.
Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir *path operation functions* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice <abbrtitle="Input/Output - Entrada/Salida: lectura o escritura en disco, comunicaciones de red.">I/O</abbr> de bloqueo.
Aun así, en ambas situaciones, es probable que **FastAPI** [siga siendo más rápida](index.md#performance) que (o al menos comparable a) tu framework anterior.
@ -10,7 +10,7 @@ La **Extensión de FastAPI** está disponible tanto para [VS Code](https://code.
### Descubrimiento de la aplicación { #application-discovery }
Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que creen un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`).
Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que crean un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`).
@ -130,7 +130,7 @@ Todos los esquemas de seguridad definidos en OpenAPI, incluyendo:
* Parámetros de query.
* Cookies, etc.
Además de todas las características de seguridad de Starlette (incluyendo **cookies de sesión**).
Además de todas las funcionalidades de seguridad de Starlette (incluyendo **cookies de sesión**).
Todo construido como herramientas y componentes reutilizables que son fáciles de integrar con tus sistemas, almacenes de datos, bases de datos relacionales y NoSQL, etc.
@ -179,7 +179,7 @@ Con **FastAPI** obtienes todas las funcionalidades de **Starlette** (ya que Fast
**FastAPI** es totalmente compatible con (y está basado en) [**Pydantic**](https://docs.pydantic.dev/). Por lo tanto, cualquier código adicional de Pydantic que tengas, también funcionará.
Incluyendo paquetes externos también basados en Pydantic, como <abbrtitle="Object-Relational Mapper - Mapeador Objeto-Relacional">ORM</abbr>s,<abbrtitle="Object-Document Mapper - Mapeador Objeto-Documento">ODM</abbr>s para bases de datos.
Incluyendo paquetes externos también basados en Pydantic, como <abbrtitle="Object-Relational Mapper - Mapeador Objeto-Relacional">ORM</abbr>s y<abbrtitle="Object-Document Mapper - Mapeador Objeto-Documento">ODM</abbr>s para bases de datos.
Esto también significa que, en muchos casos, puedes pasar el mismo objeto que obtienes de un request **directamente a la base de datos**, ya que todo se valida automáticamente.
# Introducción a Tipos en Python { #python-types-intro }
Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "type hints").
Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "anotaciones de tipos").
Estas **"anotaciones de tipos"** o type hints son una sintaxis especial que permite declarar el <dfntitle="por ejemplo: str, int, float, bool">tipo</dfn> de una variable.
Estas **"anotaciones de tipos"** o anotaciones son una sintaxis especial que permite declarar el <dfntitle="por ejemplo: str, int, float, bool">tipo</dfn> de una variable.
Al declarar tipos para tus variables, los editores y herramientas te pueden proporcionar un mejor soporte.
@ -44,7 +44,7 @@ Es un programa muy simple.
Pero ahora imagina que lo escribieras desde cero.
En algún momento habrías empezado la definición de la función, tenías los parámetros listos...
En algún momento empiezas a definir la función, y tienes los parámetros listos...
Pero luego tienes que llamar "ese método que convierte la primera letra a mayúscula".
@ -58,7 +58,7 @@ Pero, tristemente, no obtienes nada útil:
<imgsrc="/img/python-types/image01.png">
### Añadir tipos { #add-types }
### Añade tipos { #add-types }
Modifiquemos una sola línea de la versión anterior.
@ -120,7 +120,7 @@ Ahora sabes que debes corregirlo, convertir `age` a un string con `str(age)`:
Acabas de ver el lugar principal para declarar anotaciones de tipos. Como parámetros de función.
Este también es el lugar principal donde los utilizarías con **FastAPI**.
Este también es el lugar principal donde las utilizarías con **FastAPI**.
### Tipos simples { #simple-types }
@ -137,7 +137,7 @@ Puedes usar, por ejemplo:
### Módulo `typing` { #typing-module }
Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` de la standard library, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`:
Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` del paquete estándar, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`:
```python
from typing import Any
@ -149,7 +149,7 @@ def some_function(data: Any):
### Tipos genéricos { #generic-types }
Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "lista de strings" se declararía `list[str]`.
Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "list de strings" se declararía `list[str]`.
Estos tipos que pueden tomar parámetros de tipo se llaman **Tipos Genéricos** o **Genéricos**.
@ -160,7 +160,7 @@ Puedes usar los mismos tipos integrados como genéricos (con corchetes y tipos d
* `set`
* `dict`
#### Lista { #list }
#### List { #list }
Por ejemplo, vamos a definir una variable para ser una `list` de `str`.
@ -168,7 +168,7 @@ Declara la variable, con la misma sintaxis de dos puntos (`:`).
Como tipo, pon `list`.
Como la lista es un tipo que contiene algunos tipos internos, los pones entre corchetes:
Como la `list` es un tipo que contiene algunos tipos internos, los pones entre corchetes:
* `echo "*"`: "imprimirá" el texto `*` en el terminal (la siguiente parte cambia eso un poco)
* `>`: cualquier cosa impresa en el terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>`
* `echo "*"`: "imprimirá" el texto `*` en la terminal (la siguiente parte cambia eso un poco)
* `>`: cualquier cosa impresa en la terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>`
* `.gitignore`: el nombre del archivo donde debería escribirse el texto
Y `*` para Git significa "todo". Así que, ignorará todo en el directorio `.venv`.
@ -443,6 +443,8 @@ De esta manera, cuando ejecutes `python` no intentará ejecutarse desde ese ento
Ahora estás listo para empezar a trabajar en tu proyecto.
/// tip | Consejo
¿Quieres entender todo lo anterior?
@ -694,7 +696,7 @@ Eso significa que el sistema ahora comenzará a buscar primero los programas en:
antes de buscar en los otros directorios.
Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en
Así que, cuando escribas `python` en la terminal, el sistema encontrará el programa Python en
@ -800,7 +802,7 @@ $ cd ~/code/prisoner-of-azkaban
</div>
Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en el terminal, intentará usar el Python de `philosophers-stone`.
Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en la terminal, intentará usar el Python de `philosophers-stone`.