Loading

Depurando como un pro: porque llenar un script con prints es cutre

Javi Romero

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

Depurando como un pro

Porque llenar un script con prints es

HOLA

me llamo

Javi

~7 años de mi primera vez

Backend Developer en Mozio

Aficionado a la fotografía

(tranquilos luego la subo a Flickr)

Y cometo MUCHOS errores

"""
Queremos actualizar nuestros Aeropuertos con el volumen de pasajeros anual.
"""

from lugares.datos import LUGARES
from lugares.utiles import busca_volumen_pasajeros


aeropuertos = LUGARES['aeropuerto']
actualizados = 0

for aeropuerto in aeropuertos:
    if not aeropuerto.volumen:
        nuevo_volumen = busca_volumen_pasajeros(aeropuerto.codigo_iata)
        aeropuerto.volumen = nuevo_volumen
        actualizados += 1

print("Actualizados {}".format(actualizados))
Actualizados 10

Print

"""
Queremos actualizar nuestros Aeropuertos con el volumen de pasajeros anual.
"""

from lugares.datos import LUGARES
from lugares.utiles import busca_volumen_pasajeros

aeropuertos = LUGARES['aeropuerto']
actualizados = 0
sin_volumen = 0

for aeropuerto in aeropuertos:
    if not aeropuerto.volumen:
        nuevo_volumen = busca_volumen_pasajeros(aeropuerto.codigo_iata)
        aeropuerto.volumen = nuevo_volumen
        actualizados += 1
        if not aeropuerto.volumen:
            sin_volumen += 1

print("Aeropuertos {}".format(len(aeropuertos))
print("Actualizados {}".format(actualizados))
print("Sin volumen {}".format(len(sin_volumen))
Aeropuertos 10
Actualizados 3
Sin volumen 3









sin_volumen = 0






        if not aeropuerto.volumen:
            sin_volumen += 1

print("Aeropuertos {}".format(len(aeropuertos))

print("Sin volumen {}".format(len(sin_volumen))
aeropuertos_ordenados = sorted(aeropuertos, key=lambda x: x.volumen)
for aeropuerto in aeropuertos_ordenados:
    print("{}, volumen {}".format(aeropuerto.nombre, aeropuerto.volumen))


Adolfo Suárez Madrid-Barajas, volumen 46.828.279
Barcelona-El Prat, volumen 39.711.276
Palma de Mallorca, volumen 23.745.131
Malaga-Costa del Sol, volumen 14.404.170
Alicante-Elche, volumen 10.574.484
Ibiza, volumen 6.477.283
Valencia, volumen 5.051.871
Gran Canaria, volumen
Tenerife Sur, volumen
Lanzarote, volumen

Tras ejecutar nuestro script ...

Print Print

"""
Queremos actualizar nuestros Aeropuertos con el volumen de pasajeros anual.
"""

from lugares.datos import LUGARES
from lugares.utiles import busca_volumen_pasajeros

aeropuertos = LUGARES['aeropuerto']
actualizados = 0
sin_volumen = 0

for aeropuerto in aeropuertos:
    if not aeropuerto.volumen:
        print("Entra al if con aeropuerto {}".format(aeropuerto.nombre))
        nuevo_volumen = busca_volumen_pasajeros(aeropuerto.codigo_iata)
        aeropuerto.volumen = nuevo_volumen
        actualizados += 1
        if not aeropuerto.volumen:
            print("\tAeropuerto sin volumen tras actualizar!!")
            sin_volumen += 1

print("Aeropuertos {}".format(len(aeropuertos))
print("Actualizados {}".format(actualizados))
print("Sin volumen {}".format(len(sin_volumen))
Entra al if con aeropuerto Gran Canaria
    Aeropuerto sin volumen tras actualizar!!
Entra al if con aeropuerto Lanzarote
    Aeropuerto sin volumen tras actualizar!!
Entra al if con aeropuerto Tenerife Sur
    Aeropuerto sin volumen tras actualizar!!

Aeropuertos 10
Actualizados 3
Sin volumen 3













        print("Entra al if con aeropuerto {}".format(aeropuerto.nombre))




            print("\tAeropuerto sin volumen tras actualizar")

A lo mejor con otro par de prints...

Print Print Print

"""
Queremos actualizar nuestros Aeropuertos con el volumen de pasajeros anual.
"""

from lugares.datos import LUGARES
from lugares.utiles import busca_volumen_pasajeros

aeropuertos = LUGARES['aeropuerto']
actualizados = 0
sin_volumen = 0

for aeropuerto in aeropuertos:
    if not aeropuerto.volumen:
        print("Entra al if con aeropuerto {}".format(aeropuerto.nombre))
        nuevo_volumen = busca_volumen_pasajeros(aeropuerto.codigo_iata)
        print("\tRecupera volumen: {}".format(nuevo_volumen))
        aeropuerto.volumen = nuevo_volumen
        actualizados += 1
        if not aeropuerto.volumen:
            print("\tAeropuerto sin volumen tras actualizar!!")
            sin_volumen += 1

print("Aeropuertos {}".format(len(aeropuertos))
print("Actualizados {}".format(actualizados))
print("Sin volumen {}".format(len(sin_volumen))
Entra al if con aeropuerto Gran Canaria
    Recupera volumen: 
    Aeropuerto sin volumen tras actualizar!!
Entra al if con aeropuerto Lanzarote
    Recupera volumen: 
    Aeropuerto sin volumen tras actualizar!!
Entra al if con aeropuerto Tenerife Sur
    Recupera volumen: 
    Aeropuerto sin volumen tras actualizar!!

Aeropuertos 10
Actualizados 3
Sin volumen 3















        print("\tRecupera volumen: {}".format(nuevo_volumen))
Llevamos 6 prints en una función de 7 líneas
Imagina que cada búsqueda toma 2 min...

Print Print Spam Print

... y aún no sabemos qué pasa

Depuradores

Examinar el código fuente

Ver y desplazarse por la pila de llamadas

Ver los valores de variables

Establecer puntos de parada en la ejecución

Ejecutar cualquier comando en el intérprete

Depuradores - Alternativas

pdb

Incluído de serie. Allá donde tengas Python, tendrás pdb

pudb

Proporciona una interfaz gráfica para ayudar al depurado

ipdb

Mejoras al anterior: autocompletado, coloreado, introspección...

timetravelpdb

¡Te permite volver atrás en la ejecución!

ipdb

Instalarlo es muy sencillo:

Lanzarlo es también súper sencillo.

Hay varias formas de hacerlo pero vamos a la más directa que es insertando la invocación al depurador


import ipdb; ipdb.set_trace()

pip install ipdb

ipdb - Chuleta de uso rápido

  • Examinar dónde estamos
    l / list / Muestra 11 líneas alrededor de la posición
    ll / longlist / Muestra toda la función en la que estamos
    w / where / Muestra las llamadas hasta la posición actual
    p / print / Muestra el valor de una variable    
  • Controlar la ejecución
    n / next / Ejecuta hasta la siguiente línea
    s / step / Ejecuta y si hay llamadas, entra en ellas
    b / break / Añade puntos de parada
    r / return / Ejecuta hasta que la función devuelve
    c / continue / Sigue el curso de ejecución
    q / quit / Sale del depurador

Manos a la obra: resolviendo un bug

Hold onto your butts, live demo

¡Muchas gracias!

Si tenéis dudas este es un buen momento

@gooleres

flickr.com/photos/javi_romero/

bit.do/cutre

github.com/javiromero/pycones2016

Made with Slides.com