Diario de Python | #17. un paseo por Flake8
Tags: spanish, devjournal, python
Published: 2023-06-21 16:36:30

Antes de preparar una clase, investigo a fondo los temas, incluso aunque ya los conozca. Siempre se pueden encontrar nuevas formas de hacer y pensar las cosas. Por eso cuando empecé con Python y me crucé con la [PEP8](https://peps.python.org/pep-0008/), descubrí que para encontrar las formas correctas no había que irse muy lejos. Esto fue lo que me llevó a encontrarme con un corrector duro, pero justo, llamado Flake8.

## ¿Qué es la PEP8?
> La PEP8 es una guía que indica las convenciones estilísticas a seguir para escribir código Python. Se trata de un conjunto de recomendaciones cuyo objetivo es ayudar a escribir código más legible y abarca desde cómo nombrar variables, al número máximo de caracteres que una línea debe tener.

> De acuerdo con Guido van Rossum, el código es leído más veces que escrito, por lo que resulta importante escribir código que no sólo funcione correctamente, sino que además pueda ser leído con facilidad.

> [Fuente](https://ellibrodepython.com/python-pep8)

Por lo tanto, tenemos un documento que nos indica cómo escribir nuestro código de forma convencional y legible; sin tener que estar rompiéndonos la cabeza o generando nuevos estándares en el proceso.

Veamos un ejemplo del mismo documento. Aquí tenemos las formas correctas de trabajar con funciones:

```python
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

# Hanging indents should add a level.
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)
```

Y aquí las formas incorrectas:

```python
# Arguments on first line forbidden when not using vertical alignment.
foo = long_function_name(var_one, var_two,
    var_three, var_four)

# Further indentation required as indentation is not distinguishable.
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)
```

Los comentarios explican las razones de cada implementación; y podemos observar que las buenas prácticas generan código más limpio y legible.

Otro ejemplo interesante, las importaciones:

```python
# Correct:
import os
import sys

# Wrong:
import sys, os

# Correct:
from subprocess import Popen, PIPE
```

Cuando se trata de módulos separados, debemos agregar un "import" por cada uno separado por saltos de linea. Salvo que tengamos un paquete, el cual deberá importar una serie de módulos que esta vez sí serán escritos en la misma linea.

Podría armar un artículo kilométrico sobre cada buena práctica que figura en la PEP8; y seguramente más de uno debe estar preocupado por la cantidad de cosas que debe tener en cuenta a la hora de escribir un buen código. No se preocupen, porque existe una solución.

## ¡Flake8 al rescate!
[Flake8](https://pypi.org/project/flake8/) es un linter de tu código. Se asienta sobre la PEP8; y esto lo convierte en la mejor opción a la hora de ahorrarnos trabajo intentando seguir las buenas prácticas desde el método tradicional.

Implementamos un proyecto sencillo en Python, arrancando el entorno (VirtualEnv) en la carpeta del mismo (desde la terminal):

> python -m venv venv

> .\venv\Scripts\activate

Luego instalamos la dependencia de flake8

> pip install flake8

Ahora vamos a escribir un script muy sencillo, pero con todas las malas prácticas que podamos 🤣:

```python
import os, sys

name="Max" 

if name=="Max":
    print("ok")
else:
    print("wrong")
```

Me duelen un poco los ojos. Bastante. Pidámosle a flake8 que nos ayude a mejorar este...script:

> flake8 --exclude=venv

Agregamos el comando "exclude" para que evite evaluar el código de la carpeta "venv". Parece mentira, pero éste tiene muchísimos warnings y no nos servirá solucionarlo. Corremos el comando y nos devuelve esto:

![Flake8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hs1sppifxuc8vlh8vp3w.png)

En un vistazo podemos notar que primero nos indica el archivo implicado (main.py) y luego la línea y la columna de código (2:1). Luego nos indica un código (F401) que podemos buscar en [este listado de reglas de la PEP8](https://www.flake8rules.com/) si hace falta para entender a que hace referencia esta advertencia. Luego nos da una descripción del error: 'os' imported but unused. Tomé como ejemplo la primer linea para explicarlo porque todas las demás siguen el mismo patrón.

Analicemos cada error, punto por punto:
- F401: Las dependencias "os" y "sys" se importaron pero no se utilizan.
- E401: Hay múltiples imports en una sola línea.
- E225: El operador del condicional no tiene espacios.
- W291: Luego de la variable name, hay un espacio adicional.
- E225: No hay espacios entre la variable name y su asignación.
- W292: No hay un salto de línea al final del script.

Gracias a Flake8 podemos notar todos los warnings de una sola pasada. Vamos a arreglar el script y correrlo de nuevo. El objetivo es que nuestro comando no arroje ningun error, por lo tanto quede vacío. El código quedará así:

```python
name = "Max"

if name == "Max":
    print("ok")
else:
    print("wrong")

```

Pueden notar un cambio muy positivo, desde la legibilidad del código hasta su acotamiento. Si nos mantenemos en los principios del PEP8 y utilizamos linters, podremos seguir las buenas prácticas sin apenas despeinarnos.

## Conclusiones
Soy consciente de lo duro que es desarrollar correctamente: a veces la falta de tiempos y la planificación nos impulsan a resolver todo antes que dejarlo bonito. No obstante, hacer las cosas correctamente desde el principio, nos va ahorrar tener que trabajar el doble para arreglarlas en el futuro. Una guía de estilo como PEP8, conjunto de un buen linter como Flake8, nos facilitan la vida a corto, mediano y largo plazo.

Si quieren ver un ejemplo más real aplicado, pueden analizar este [commit](https://github.com/maxwellnewage/python-practices/commit/49c2ea25b39f8477d4ba7764ef27cf04ef0802d9) que hice a mi repositorio de prácticas en Python, donde apliqué Flake8 y cambié muchísimos scripts.