Revisar el manejo de excepciones en funciones simples

PythonPythonBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, aprenderás cómo revisar la definición de funciones simples en Python y explorar el manejo de excepciones. Las funciones son un concepto clave de programación que te permite estructurar el código en segmentos reutilizables. El manejo de excepciones, por otro lado, es un método para tratar los errores y las circunstancias imprevistas en tus programas.

Los principales objetivos de este laboratorio son revisar el proceso de definición de funciones simples y aprender sobre el manejo de excepciones en Python. El archivo que se modificará es pcost.py.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python/BasicConceptsGroup -.-> python/python_shell("Python Shell") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/FileHandlingGroup -.-> python/file_opening_closing("Opening and Closing Files") python/FileHandlingGroup -.-> python/file_reading_writing("Reading and Writing Files") subgraph Lab Skills python/python_shell -.-> lab-132393{{"Revisar el manejo de excepciones en funciones simples"}} python/function_definition -.-> lab-132393{{"Revisar el manejo de excepciones en funciones simples"}} python/catching_exceptions -.-> lab-132393{{"Revisar el manejo de excepciones en funciones simples"}} python/file_opening_closing -.-> lab-132393{{"Revisar el manejo de excepciones en funciones simples"}} python/file_reading_writing -.-> lab-132393{{"Revisar el manejo de excepciones en funciones simples"}} end

Definición de una función

En este paso, aprenderemos cómo crear una función. Una función en Python es un bloque de código organizado y reutilizable que se utiliza para realizar una única acción relacionada. Aquí, nuestra función leerá los datos de una cartera (portfolio) desde un archivo y calculará el costo total. Esto es útil porque una vez que tenemos esta función, podemos usarla múltiples veces con diferentes archivos de cartera, evitando tener que escribir el mismo código una y otra vez.

Comprensión del problema

En el laboratorio anterior, es posible que hayas escrito algún código para leer los datos de una cartera y calcular el costo total. Pero ese código probablemente se escribió de una manera que no se puede reutilizar fácilmente. Ahora, vamos a convertir ese código en una función reutilizable.

Los archivos de datos de cartera tienen un formato específico. Contienen información en la forma de "Símbolo Acciones Precio". Cada línea en el archivo representa una inversión en una acción. Por ejemplo, en un archivo llamado portfolio.dat, podrías ver líneas como esta:

AA 100 32.20
IBM 50 91.10
...

Aquí, la primera parte (como "AA" o "IBM") es el símbolo de la acción, que es un identificador único para la acción. La segunda parte es el número de acciones que posees de esa acción, y la tercera parte es el precio por acción.

Creación de la función

Vamos a crear un archivo de Python llamado pcost.py en el directorio /home/labex/project. Este archivo contendrá nuestra función. Aquí está el código que pondremos en el archivo pcost.py:

def portfolio_cost(filename):
    """
    Computes the total cost (shares*price) of a portfolio file

    Args:
        filename: The name of the portfolio file

    Returns:
        The total cost of the portfolio as a float
    """
    total_cost = 0.0

    ## Open the file and read through each line
    with open(filename, 'r') as f:
        for line in f:
            fields = line.split()
            ## Extract the data (symbol, shares, price)
            shares = int(fields[1])
            price = float(fields[2])
            ## Add the cost to our running total
            total_cost += shares * price

    return total_cost

## Call the function with the portfolio.dat file
if __name__ == '__main__':
    cost = portfolio_cost('/home/labex/project/portfolio.dat')
    print(cost)

En este código, primero definimos una función llamada portfolio_cost que toma un filename como argumento. Dentro de la función, inicializamos una variable total_cost a 0.0. Luego abrimos el archivo usando la función open en modo lectura ('r'). Usamos un bucle for para recorrer cada línea del archivo. Para cada línea, la dividimos en campos usando el método split(). Luego extraemos el número de acciones y lo convertimos a un entero, y el precio y lo convertimos a un número de punto flotante. Calculamos el costo de esa inversión en acciones multiplicando el número de acciones por el precio y lo sumamos al total_cost. Finalmente, devolvemos el total_cost.

La parte if __name__ == '__main__': se utiliza para llamar a la función cuando el script se ejecuta directamente. Pasamos la ruta al archivo portfolio.dat a la función y mostramos el resultado.

Prueba de la función

Ahora, vamos a ejecutar el programa para ver si funciona. Necesitamos navegar al directorio donde se encuentra el archivo pcost.py y luego ejecutar el script de Python. Aquí están los comandos para hacer eso:

cd /home/labex/project
python3 pcost.py

Después de ejecutar estos comandos, deberías ver la salida:

44671.15

Esta salida representa el costo total de todas las acciones en la cartera.

Comprensión del código

Vamos a desglosar lo que hace nuestra función paso a paso:

  1. Toma un filename como parámetro de entrada. Esto nos permite usar la función con diferentes archivos de cartera.
  2. Abre el archivo y lo lee línea por línea. Esto se hace usando la función open y un bucle for.
  3. Para cada línea, la divide en campos usando el método split(). Este método divide la línea en una lista de cadenas basada en los espacios en blanco.
  4. Convierte el número de acciones a un entero y el precio a un número de punto flotante. Esto es necesario porque los datos leídos del archivo están en formato de cadena, y necesitamos realizar operaciones aritméticas con ellos.
  5. Calcula el costo (acciones * precio) para cada inversión en acciones y lo suma al total acumulado. Esto nos da el costo total de la cartera.
  6. Devuelve el costo total final. Esto nos permite usar el resultado en otras partes de nuestro programa si es necesario.

Esta función ahora es reutilizable. Podemos llamarla con diferentes archivos de cartera para calcular sus costos, lo que hace que nuestro código sea más eficiente y más fácil de mantener.

✨ Revisar Solución y Practicar

Incorporación del manejo de errores

Cuando se trabaja con datos del mundo real, es muy común encontrar inconsistencias o errores. Por ejemplo, los datos pueden tener valores faltantes, formatos incorrectos u otros problemas. Python ofrece mecanismos de manejo de excepciones para tratar estas situaciones de manera elegante. El manejo de excepciones permite que tu programa siga ejecutándose incluso cuando encuentra un error, en lugar de terminar abruptamente.

Comprensión del problema

Echemos un vistazo al archivo portfolio3.dat. Este archivo contiene algunos datos sobre una cartera (portfolio), como el símbolo de la acción, el número de acciones y el precio por acción. Para ver el contenido de este archivo, podemos usar el siguiente comando:

cat /home/labex/project/portfolio3.dat

Cuando ejecutes este comando, notarás que algunas líneas del archivo tienen guiones (-) en lugar de números para el número de acciones. Aquí tienes un ejemplo de lo que podrías ver:

AA 100 32.20
IBM 50 91.10
C - 53.08
...

Si intentamos ejecutar nuestro código actual con este archivo, se detendrá con un error. La razón es que nuestro código espera convertir el número de acciones en un entero, pero no puede convertir un guión (-) en un entero. Intentemos ejecutar el código y veamos qué sucede:

python3 -c "import sys; sys.path.append('/home/labex/project'); from pcost import portfolio_cost; print(portfolio_cost('/home/labex/project/portfolio3.dat'))"

Verás un mensaje de error como este:

ValueError: invalid literal for int() with base 10: '-'

Este error se produce porque Python no puede convertir el carácter - en un entero cuando intenta ejecutar int(fields[1]).

Introducción al manejo de excepciones

El manejo de excepciones en Python utiliza bloques try y except. El bloque try contiene el código que podría generar una excepción. Una excepción es un error que ocurre durante la ejecución de un programa. El bloque except contiene el código que se ejecutará si se produce una excepción en el bloque try.

Aquí tienes un ejemplo de cómo funcionan los bloques try y except:

try:
    ## Code that might raise an exception
    result = risky_operation()
except ExceptionType as e:
    ## Code to handle the exception
    print(f"An error occurred: {e}")

Cuando Python ejecuta el código en el bloque try, si se produce una excepción, la ejecución salta inmediatamente al bloque except coincidente. El ExceptionType en el bloque except especifica el tipo de excepción que queremos manejar. La variable e contiene información sobre la excepción, como el mensaje de error.

Modificación de la función con manejo de excepciones

Vamos a actualizar nuestro archivo pcost.py para manejar los errores en los datos. Usaremos los bloques try y except para omitir las líneas con datos incorrectos y mostrar un mensaje de advertencia.

def portfolio_cost(filename):
    """
    Computes the total cost (shares*price) of a portfolio file
    Handles lines with bad data by skipping them and showing a warning.

    Args:
        filename: The name of the portfolio file

    Returns:
        The total cost of the portfolio as a float
    """
    total_cost = 0.0

    ## Open the file and read through each line
    with open(filename, 'r') as f:
        for line in f:
            fields = line.split()
            try:
                ## Extract the data (symbol, shares, price)
                shares = int(fields[1])
                price = float(fields[2])
                ## Add the cost to our running total
                total_cost += shares * price
            except ValueError as e:
                ## Print a warning for lines that can't be parsed
                print(f"Couldn't parse: '{line}'")
                print(f"Reason: {e}")

    return total_cost

## Call the function with the portfolio3.dat file
if __name__ == '__main__':
    cost = portfolio_cost('/home/labex/project/portfolio3.dat')
    print(cost)

En este código actualizado, primero abrimos el archivo y lo leemos línea por línea. Para cada línea, la dividimos en campos. Luego, intentamos convertir el número de acciones en un entero y el precio en un número de punto flotante. Si esta conversión falla (es decir, se produce un ValueError), mostramos un mensaje de advertencia y omitimos esa línea. De lo contrario, calculamos el costo de las acciones y lo sumamos al costo total.

Prueba de la función actualizada

Ahora, ejecutemos el programa actualizado con el archivo problemático. Primero, debemos navegar al directorio del proyecto y luego podemos ejecutar el script de Python.

cd /home/labex/project
python3 pcost.py

Deberías ver una salida como esta:

Couldn't parse: 'C - 53.08
'
Reason: invalid literal for int() with base 10: '-'
Couldn't parse: 'DIS - 34.20
'
Reason: invalid literal for int() with base 10: '-'
44671.15

El programa ahora hace lo siguiente:

  1. Intenta procesar cada línea del archivo.
  2. Si una línea contiene datos no válidos, captura el ValueError.
  3. Muestra un mensaje útil sobre el problema.
  4. Continúa procesando el resto del archivo.
  5. Devuelve el costo total basado en las líneas válidas.

Este enfoque hace que nuestro programa sea mucho más robusto al tratar con datos imperfectos. Puede manejar los errores de manera elegante y aún proporcionar resultados útiles.

✨ Revisar Solución y Practicar

Experimentación interactiva

Python ofrece un modo interactivo que te permite ejecutar código de inmediato. Esto es muy útil para probar tu código y probar cosas nuevas. En este paso, aprenderemos cómo llamar a una función directamente desde el intérprete de Python.

Ejecución de Python en modo interactivo

Para ejecutar un script de Python y luego entrar en el modo interactivo, puedes usar la bandera -i. Esta bandera le dice a Python que siga ejecutándose en un estado interactivo después de ejecutar el script. Así es como se hace:

cd /home/labex/project
python3 -i pcost.py

Desglosemos lo que hace este comando:

  1. Primero, cd /home/labex/project cambia el directorio actual a /home/labex/project. Aquí es donde se encuentra nuestro script pcost.py.
  2. Luego, python3 -i pcost.py ejecuta el script pcost.py. Después de que el script termine de ejecutarse, Python permanece en modo interactivo.
  3. En modo interactivo, puedes escribir comandos de Python directamente en la terminal.

Después de ejecutar el comando, verás la salida del script pcost.py, seguida del indicador de Python (>>>). Este indicador indica que ahora puedes ingresar comandos de Python.

Llamada a tu función de forma interactiva

Una vez que estés en el modo interactivo, puedes llamar a la función portfolio_cost() con diferentes nombres de archivo. Esto te permite ver cómo se comporta la función con diversas entradas. Aquí tienes un ejemplo:

>>> portfolio_cost('/home/labex/project/portfolio.dat')
44671.15
>>> portfolio_cost('/home/labex/project/portfolio2.dat')
19908.75
>>> portfolio_cost('/home/labex/project/portfolio3.dat')
Couldn't parse: 'C - 53.08
'
Reason: invalid literal for int() with base 10: '-'
Couldn't parse: 'DIS - 34.20
'
Reason: invalid literal for int() with base 10: '-'
44671.15

Utilizando este enfoque interactivo, puedes:

  • Probar tu función con diferentes entradas para ver si funciona como se espera.
  • Experimentar con el comportamiento de la función en diversas condiciones.
  • Depurar tu código sobre la marcha viendo los resultados inmediatos de tus llamadas a la función.

Beneficios del modo interactivo

El modo interactivo tiene varios beneficios:

  1. Puedes probar rápidamente diferentes escenarios sin tener que ejecutar todo el script cada vez.
  2. Puedes inspeccionar variables y resultados de expresiones inmediatamente, lo que te ayuda a entender lo que está sucediendo en tu código.
  3. Puedes probar pequeños fragmentos de código sin crear un programa completo. Esto es genial para aprender y probar nuevas ideas.
  4. Es una excelente manera de aprender y experimentar con Python porque obtienes retroalimentación instantánea.

Salida del modo interactivo

Cuando hayas terminado de experimentar, puedes salir del modo interactivo de dos maneras:

  • Escribe exit() y presiona Enter. Esta es una forma directa de terminar la sesión interactiva.
  • Presiona Ctrl+D (en Unix/Linux). Esta es una combinación de teclas que también sale del modo interactivo.

A lo largo de tu viaje de programación en Python, la técnica de definir funciones y probarlas de forma interactiva será extremadamente valiosa para el desarrollo y la depuración. Te permite iterar rápidamente en tu código y encontrar y corregir problemas.

✨ Revisar Solución y Practicar

Resumen

En este laboratorio (lab), has aprendido varios conceptos clave de programación en Python. En primer lugar, has aprendido cómo definir y utilizar funciones, lo que hace que tu código sea reutilizable. En segundo lugar, has dominado la implementación del manejo de excepciones, lo que mejora la robustez de tus programas. Por último, has descubierto cómo usar Python en modo interactivo para pruebas y experimentación.

Estas habilidades son fundamentales para escribir programas de Python confiables. Las funciones ayudan a organizar y reutilizar el código, el manejo de excepciones permite manejar de manera elegante situaciones inesperadas y el modo interactivo ofrece un entorno poderoso para pruebas y depuración. A medida que avances en tu aprendizaje de Python, estos conceptos resultarán cada vez más valiosos para desarrollar aplicaciones más grandes y complejas.