Utilizar generadores para tuberías de simulación de acciones (stocksim)

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 aprovechar los generadores de Python para construir eficientes tuberías de procesamiento de datos. Los generadores son una poderosa característica de Python que permite la producción de datos a demanda, eliminando la necesidad de almacenar todos los datos en memoria al mismo tiempo. Descubrirás cómo conectar generadores para crear flujos de trabajo de procesamiento de datos similares a las tuberías Unix.

Los objetivos de este laboratorio son comprender los fundamentos de las tuberías de procesamiento basadas en generadores, crear flujos de trabajo de procesamiento de datos utilizando generadores de Python y filtrar y formatear flujos de datos en tiempo real. El archivo ticker.py se creará durante este laboratorio. Ten en cuenta que para este ejercicio, el programa stocksim.py debe estar ejecutándose en segundo plano, y utilizarás la función follow() de un ejercicio anterior.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/PythonStandardLibraryGroup(["Python Standard Library"]) python(("Python")) -.-> python/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") python/ObjectOrientedProgrammingGroup -.-> python/constructor("Constructor") python/FileHandlingGroup -.-> python/file_reading_writing("Reading and Writing Files") python/FileHandlingGroup -.-> python/file_operations("File Operations") python/AdvancedTopicsGroup -.-> python/generators("Generators") python/PythonStandardLibraryGroup -.-> python/data_collections("Data Collections") subgraph Lab Skills python/classes_objects -.-> lab-132523{{"Utilizar generadores para tuberías de simulación de acciones (stocksim)"}} python/constructor -.-> lab-132523{{"Utilizar generadores para tuberías de simulación de acciones (stocksim)"}} python/file_reading_writing -.-> lab-132523{{"Utilizar generadores para tuberías de simulación de acciones (stocksim)"}} python/file_operations -.-> lab-132523{{"Utilizar generadores para tuberías de simulación de acciones (stocksim)"}} python/generators -.-> lab-132523{{"Utilizar generadores para tuberías de simulación de acciones (stocksim)"}} python/data_collections -.-> lab-132523{{"Utilizar generadores para tuberías de simulación de acciones (stocksim)"}} end

Tubería básica de generadores con datos CSV

En este paso, aprenderemos cómo crear una tubería de procesamiento básica utilizando generadores. Pero primero, entendamos qué son los generadores. Los generadores son un tipo especial de iterador en Python. A diferencia de los iteradores normales que pueden cargar todos los datos en memoria a la vez, los generadores generan valores a demanda. Esto es extremadamente útil cuando se trabaja con grandes flujos de datos porque ahorra memoria. En lugar de tener que almacenar todo el conjunto de datos en memoria, el generador produce valores uno por uno según los necesites.

Comprender los generadores

Un generador es esencialmente una función que devuelve un iterador. Cuando iteras sobre este iterador, produce una secuencia de valores. La forma en que se escribe una función generadora es similar a una función normal, pero hay una diferencia clave. En lugar de usar la declaración return, una función generadora utiliza la declaración yield. La declaración yield tiene un comportamiento único. Pausa la función y guarda su estado actual. Cuando se solicita el siguiente valor, la función continúa desde donde se detuvo. Esto permite que el generador produzca valores de forma incremental sin tener que comenzar desde el principio cada vez.

Usar la función follow()

La función follow() que creaste anteriormente funciona de manera similar al comando Unix tail -f. El comando tail -f monitorea continuamente un archivo en busca de nuevo contenido, y lo mismo hace la función follow(). Ahora, usémosla para crear una simple tubería de procesamiento.

Paso 1: Abrir una nueva ventana de terminal

Primero, abre una nueva ventana de terminal en el WebIDE. Puedes hacerlo yendo a Terminal → New Terminal. Esta nueva terminal será donde ejecutaremos nuestros comandos de Python.

Paso 2: Iniciar una shell interactiva de Python

Una vez que la nueva terminal esté abierta, inicia una shell interactiva de Python. Puedes hacerlo ingresando el siguiente comando en la terminal:

python3

La shell interactiva de Python te permite ejecutar código de Python línea por línea y ver los resultados inmediatamente.

Paso 3: Importar la función follow y configurar la tubería

Ahora, importaremos la función follow y configuraremos una tubería básica para leer los datos de las acciones. En la shell interactiva de Python, ingresa el siguiente código:

>>> from follow import follow
>>> import csv
>>> lines = follow('stocklog.csv')
>>> rows = csv.reader(lines)
>>> for row in rows:
...     print(row)
...

Esto es lo que hace cada línea:

  • from follow import follow: Esto importa la función follow del módulo follow.
  • import csv: Esto importa el módulo csv, que se utiliza para leer y escribir archivos CSV en Python.
  • lines = follow('stocklog.csv'): Esto llama a la función follow con el nombre de archivo stocklog.csv. La función follow devuelve un generador que produce nuevas líneas a medida que se agregan al archivo.
  • rows = csv.reader(lines): La función csv.reader() toma las líneas generadas por la función follow y las analiza en filas de datos CSV.
  • El bucle for itera a través de estas filas y las imprime una por una.

Paso 4: Verificar la salida

Después de ejecutar el código, deberías ver una salida similar a esta (tus datos variarán):

['BA', '98.35', '6/11/2007', '09:41.07', '0.16', '98.25', '98.35', '98.31', '158148']
['AA', '39.63', '6/11/2007', '09:41.07', '-0.03', '39.67', '39.63', '39.31', '270224']
['XOM', '82.45', '6/11/2007', '09:41.07', '-0.23', '82.68', '82.64', '82.41', '748062']
['PG', '62.95', '6/11/2007', '09:41.08', '-0.12', '62.80', '62.97', '62.61', '454327']
...

Esta salida indica que has creado exitosamente una tubería de datos. La función follow() genera líneas del archivo, y luego estas líneas se pasan a la función csv.reader(), que las analiza en filas de datos.

Si has visto suficiente salida, puedes detener la ejecución presionando Ctrl+C.

¿Qué está pasando?

Desglosemos lo que está sucediendo en esta tubería:

  1. follow('stocklog.csv') crea un generador. Este generador sigue el archivo stocklog.csv y produce nuevas líneas a medida que se agregan al archivo.
  2. csv.reader(lines) toma las líneas generadas por la función follow y las analiza en datos de filas CSV. Entiende la estructura de los archivos CSV y divide las líneas en valores individuales.
  3. Luego, el bucle for itera a través de estas filas, imprimiendo cada una. Esto te permite ver los datos en un formato legible.

Este es un ejemplo simple de una tubería de procesamiento de datos utilizando generadores. En los siguientes pasos, construiremos tuberías más complejas y útiles.

Creación de la clase Ticker

En el procesamiento de datos, trabajar con datos sin procesar puede ser bastante desafiante. Para que nuestro trabajo con los datos de acciones sea más organizado y eficiente, definiremos una clase adecuada para representar las cotizaciones de acciones. Esta clase servirá como un modelo para nuestros datos de acciones, lo que hará que nuestra tubería de procesamiento de datos sea más robusta y fácil de administrar.

Creación del archivo ticker.py

  1. Primero, necesitamos crear un nuevo archivo en el WebIDE. Puedes hacerlo haciendo clic en el icono "New File" o haciendo clic derecho en el explorador de archivos y seleccionando "New File". Nombrar este archivo ticker.py. Este archivo contendrá el código de nuestra clase Ticker.

  2. Ahora, agreguemos el siguiente código al archivo ticker.py recién creado. Este código definirá nuestra clase Ticker y configurará una simple tubería de procesamiento para probarla.

## ticker.py

from structure import Structure, String, Float, Integer

class Ticker(Structure):
    name = String()
    price = Float()
    date = String()
    time = String()
    change = Float()
    open = Float()
    high = Float()
    low = Float()
    volume = Integer()

if __name__ == '__main__':
    from follow import follow
    import csv
    lines = follow('stocklog.csv')
    rows = csv.reader(lines)
    records = (Ticker.from_row(row) for row in rows)
    for record in records:
        print(record)
  1. Después de agregar el código, guarda el archivo. Puedes hacerlo presionando Ctrl+S o seleccionando "File" → "Save" desde el menú. Guardar el archivo asegura que tus cambios se conserven y se puedan ejecutar más tarde.

Comprensión del código

Echemos un vistazo más detallado a lo que hace este código paso a paso:

  1. Al principio del código, estamos importando Structure y tipos de campos del módulo structure.py. Este módulo ya se ha configurado para ti. Estas importaciones son esenciales porque proporcionan los bloques de construcción para nuestra clase Ticker. La clase Structure será la clase base para nuestra clase Ticker, y los tipos de campos como String, Float e Integer definirán los tipos de datos de nuestros campos de datos de acciones.

  2. A continuación, definimos una clase Ticker que hereda de Structure. Esta clase tiene varios campos que representan diferentes aspectos de los datos de acciones:

    • name: Este campo almacena el símbolo de la acción, como "IBM" o "AAPL". Nos ayuda a identificar de qué empresa es la acción con la que estamos trabajando.
    • price: Contiene el precio actual de la acción. Esta es una información crucial para los inversionistas.
    • date y time: Estos campos nos indican cuándo se generó la cotización de la acción. Saber la hora y la fecha es importante para analizar las tendencias de precios de las acciones a lo largo del tiempo.
    • change: Esto representa el cambio de precio de la acción. Muestra si el precio de la acción ha subido o bajado en comparación con un punto anterior.
    • open, high, low: Estos campos representan el precio de apertura, el precio más alto y el precio más bajo de la acción durante un cierto período. Nos dan una idea del rango de precios de la acción.
    • volume: Este campo almacena el número de acciones negociadas. Un alto volumen de negociación puede indicar un fuerte interés del mercado en una acción en particular.
  3. En el bloque if __name__ == '__main__':, configuramos una tubería de procesamiento. Este bloque de código se ejecutará cuando ejecutemos directamente el archivo ticker.py.

    • follow('stocklog.csv') es una función que genera líneas del archivo stocklog.csv. Nos permite leer el archivo línea por línea.
    • csv.reader(lines) toma estas líneas y las analiza en datos de filas. CSV (Comma - Separated Values) es un formato de archivo común para almacenar datos tabulares, y esta función nos ayuda a extraer los datos de cada fila.
    • (Ticker.from_row(row) for row in rows) es una expresión generadora. Toma cada fila de datos y la convierte en un objeto Ticker. De esta manera, transformamos los datos CSV sin procesar en objetos estructurados que son más fáciles de manejar.
    • El bucle for itera sobre estos objetos Ticker y los imprime uno por uno. Esto nos permite ver los datos estructurados en acción.

Ejecución del código

Ejecutemos el código para ver cómo funciona:

  1. Primero, debemos asegurarnos de que estamos en el directorio del proyecto en la terminal. Si no estás allí, utiliza el siguiente comando para navegar hasta él:

    cd /home/labex/project
  2. Una vez que estés en el directorio correcto, ejecuta el script ticker.py utilizando el siguiente comando:

    python3 ticker.py
  3. Después de ejecutar el script, deberías ver una salida similar a esta (tus datos variarán):

    Ticker(IBM, 103.53, 6/11/2007, 09:53.59, 0.46, 102.87, 103.53, 102.77, 541633)
    Ticker(MSFT, 30.21, 6/11/2007, 09:54.01, 0.16, 30.05, 30.21, 29.95, 7562516)
    Ticker(AA, 40.01, 6/11/2007, 09:54.01, 0.35, 39.67, 40.15, 39.31, 576619)
    Ticker(T, 40.1, 6/11/2007, 09:54.08, -0.16, 40.2, 40.19, 39.87, 1312959)

Puedes detener la ejecución del script presionando Ctrl+C cuando hayas visto suficiente salida.

Observa cómo los datos CSV sin procesar se han transformado en objetos Ticker estructurados. Esta transformación hace que los datos sean mucho más fáciles de manejar en nuestra tubería de procesamiento, ya que ahora podemos acceder y manipular los datos de acciones utilizando los campos definidos en la clase Ticker.

✨ Revisar Solución y Practicar

Construcción de una tubería de datos más compleja

Ahora, llevaremos nuestra tubería de datos al siguiente nivel agregando filtrado y mejorando la presentación de los datos. Esto hará que sea más fácil analizar y entender la información con la que estamos trabajando. Realizaremos cambios en nuestro script ticker.py. Filtrar los datos nos ayudará a centrarnos en la información específica que nos interesa, y presentarla en una tabla bien formateada la hará más legible.

Actualización del archivo ticker.py

  1. Primero, abre tu archivo ticker.py en el WebIDE. El WebIDE es una herramienta que te permite escribir y editar código directamente en tu navegador. Proporciona un entorno conveniente para realizar cambios en tus scripts de Python.

  2. A continuación, necesitamos reemplazar el bloque if __name__ == '__main__': en el archivo ticker.py con el siguiente código. Este bloque de código es el punto de entrada de nuestro script, y al reemplazarlo, estaremos cambiando cómo el script procesa y muestra los datos.

if __name__ == '__main__':
    from follow import follow
    import csv
    from tableformat import create_formatter, print_table

    formatter = create_formatter('text')

    lines = follow('stocklog.csv')
    rows = csv.reader(lines)
    records = (Ticker.from_row(row) for row in rows)
    negative = (rec for rec in records if rec.change < 0)
    print_table(negative, ['name', 'price', 'change'], formatter)
  1. Después de realizar estos cambios, guarda el archivo. Puedes hacerlo presionando Ctrl+S en tu teclado o seleccionando "File" → "Save" desde el menú. Guardar el archivo asegura que tus cambios se conserven y se puedan ejecutar más tarde.

Comprensión de la tubería mejorada

Echemos un vistazo más detallado a lo que hace esta tubería mejorada. Comprender cada paso te ayudará a ver cómo las diferentes partes del código trabajan juntas para procesar y mostrar los datos.

  1. Comenzamos importando create_formatter y print_table del módulo tableformat. Este módulo ya está configurado para ti y proporciona funciones que nos ayudan a formatear y mostrar los datos en una tabla agradable.

  2. Luego, creamos un formateador de texto utilizando create_formatter('text'). Este formateador se utilizará para formatear los datos de una manera fácil de leer.

  3. Ahora, desglosemos la tubería paso a paso:

    • follow('stocklog.csv') es una función que genera líneas del archivo stocklog.csv. Monitorea continuamente el archivo en busca de nuevos datos y proporciona las líneas una por una.
    • csv.reader(lines) toma las líneas generadas por follow y las analiza en datos de filas. Esto es necesario porque los datos en el archivo CSV están en formato de texto y necesitamos convertirlos en un formato estructurado con el que podamos trabajar.
    • (Ticker.from_row(row) for row in rows) es una expresión generadora que convierte cada fila de datos en un objeto Ticker. Un objeto Ticker representa una acción y contiene información como el nombre de la acción, el precio y el cambio.
    • (rec for rec in records if rec.change < 0) es otra expresión generadora que filtra los objetos Ticker. Solo conserva los objetos donde el cambio de precio de la acción es negativo. Esto nos permite centrarnos en las acciones que han disminuido de precio.
    • print_table(negative, ['name', 'price', 'change'], formatter) toma los objetos Ticker filtrados y los formatea en una tabla utilizando el formateador que creamos anteriormente. Luego, muestra la tabla en la consola.

Esta tubería demuestra el poder de los generadores. En lugar de cargar todos los datos del archivo en memoria a la vez, estamos encadenando múltiples operaciones (lectura, análisis, conversión, filtrado) y procesando los datos uno por uno. Esto ahorra memoria y hace que el código sea más eficiente.

Ejecución de la tubería mejorada

Ejecutemos el código actualizado para ver los resultados.

  1. Primero, asegúrate de que estás en el directorio del proyecto en la terminal. Si no estás allí, puedes navegar hasta él utilizando el siguiente comando:

    cd /home/labex/project
  2. Una vez que estés en el directorio del proyecto, ejecuta el script ticker.py utilizando el siguiente comando:

    python3 ticker.py
  3. Después de ejecutar el script, deberías ver una tabla bien formateada en la terminal. Esta tabla muestra solo las acciones con cambios de precio negativos.

           name      price     change
     ---------- ---------- ----------
              C      53.12      -0.21
            UTX      70.04      -0.19
            AXP      62.86      -0.18
            MMM      85.72      -0.22
            MCD      51.38      -0.03
            WMT      49.85      -0.23
             KO       51.6      -0.07
            AIG      71.39      -0.14
             PG      63.05      -0.02
             HD      37.76      -0.19

Si has visto suficiente salida y quieres detener la ejecución del script, puedes presionar Ctrl+C en tu teclado.

El poder de las tuberías de generadores

Lo que hemos creado aquí es una poderosa tubería de procesamiento de datos. Resumamos lo que hace:

  1. Monitorea continuamente el archivo stocklog.csv en busca de nuevos datos. Esto significa que a medida que se agreguen nuevos datos al archivo, la tubería los procesará automáticamente.
  2. Analiza los datos CSV del archivo en objetos Ticker estructurados. Esto hace que sea más fácil trabajar con los datos y realizar operaciones en ellos.
  3. Filtra los datos según un criterio específico, en este caso, cambios de precio negativos. Esto nos permite centrarnos en las acciones que están perdiendo valor.
  4. Formatea y presenta los datos filtrados en una tabla legible. Esto hace que sea fácil analizar los datos y sacar conclusiones.

Una de las principales ventajas de usar generadores en esta tubería es que utiliza una cantidad mínima de memoria. Los generadores producen valores a demanda, lo que significa que no almacenan todos los datos en memoria a la vez. Esto es similar a las tuberías Unix, donde cada componente procesa los datos y los pasa al siguiente componente.

Puedes pensar en los generadores como bloques de Lego. Al igual que puedes apilar bloques de Lego para crear diferentes estructuras, puedes combinar generadores para crear flujos de trabajo de procesamiento de datos poderosos. Este enfoque modular te permite construir sistemas complejos a partir de componentes simples y reutilizables.

✨ Revisar Solución y Practicar

Resumen

En este laboratorio, has aprendido cómo utilizar generadores de Python para construir tuberías de procesamiento de datos eficientes. Completaste varias tareas importantes, como utilizar la función follow() para monitorear un archivo en busca de nuevos datos, crear una clase Ticker para representar las cotizaciones de acciones y construir una tubería de procesamiento de múltiples etapas que lee, analiza y filtra datos CSV, y luego formatea y muestra los resultados.

El enfoque basado en generadores ofrece múltiples ventajas, incluyendo eficiencia de memoria ya que los datos se procesan a demanda, modularidad que permite la fácil combinación y reutilización de componentes de la tubería, y simplicidad en la expresión de flujos de datos complejos. Estos conceptos se aplican comúnmente en el procesamiento de datos del mundo real, especialmente para conjuntos de datos grandes o datos en streaming.