Введение
В этом практическом занятии (лабораторной работе) вы научитесь использовать генераторы Python для создания эффективных конвейеров обработки данных. Генераторы - это мощная функция Python, которая позволяет создавать данные по запросу, избавляя от необходимости хранить все данные в памяти одновременно. Вы узнаете, как соединить генераторы для создания рабочих процессов обработки данных, аналогичных Unix-каналам (pipes).
Цели этого практического занятия (лабораторной работы) - понять основы конвейеров обработки на основе генераторов, создать рабочие процессы обработки данных с использованием генераторов Python и фильтровать и форматировать потоки реального времени. Файл ticker.py будет создан в рамках этого практического занятия. Обратите внимание, что для этого упражнения программа stocksim.py должна работать в фоновом режиме, и вы будете использовать функцию follow() из предыдущего упражнения.
Базовый конвейер генераторов с данными в формате CSV
На этом этапе мы научимся создавать базовый конвейер обработки данных с использованием генераторов. Но сначала разберемся, что такое генераторы. Генераторы - это особый тип итераторов в Python. В отличие от обычных итераторов, которые могут загрузить все данные в память сразу, генераторы создают значения по запросу. Это чрезвычайно полезно при работе с большими потоками данных, так как экономит память. Вместо того чтобы хранить весь набор данных в памяти, генератор создает значения по одному по мере необходимости.
Понимание генераторов
Генератор по сути представляет собой функцию, которая возвращает итератор. Когда вы итерируете по этому итератору, он создает последовательность значений. Запись функции - генератора похожа на запись обычной функции, но есть важное различие. Вместо оператора return функция - генератор использует оператор yield. Оператор yield имеет уникальное поведение. Он приостанавливает функцию и сохраняет ее текущее состояние. Когда запрашивается следующее значение, функция продолжает работу с того места, где остановилась. Это позволяет генератору создавать значения пошагово, не требуя каждый раз начинать с начала.
Использование функции follow()
Функция follow(), которую вы создали ранее, работает аналогично команде Unix tail -f. Команда tail -f постоянно отслеживает файл на предмет появления нового содержимого, и то же делает функция follow(). Теперь используем ее для создания простого конвейера обработки данных.
Шаг 1: Откройте новое окно терминала
Сначала откройте новое окно терминала в WebIDE. Вы можете сделать это, выбрав Terminal → New Terminal. В этом новом терминале мы будем запускать наши команды Python.
Шаг 2: Запустите интерактивную оболочку Python
После открытия нового терминала запустите интерактивную оболочку Python. Вы можете сделать это, введя следующую команду в терминале:
python3
Интерактивная оболочка Python позволяет запускать код Python построчно и сразу видеть результаты.
Шаг 3: Импортируйте функцию follow и настройте конвейер
Теперь импортируем функцию follow и настроим базовый конвейер для чтения данных о ценах на акции. В интерактивной оболочке Python введите следующий код:
>>> from follow import follow
>>> import csv
>>> lines = follow('stocklog.csv')
>>> rows = csv.reader(lines)
>>> for row in rows:
... print(row)
...
Вот что делает каждая строка:
from follow import follow: Эта строка импортирует функциюfollowиз модуляfollow.import csv: Эта строка импортирует модульcsv, который используется для чтения и записи файлов в формате CSV в Python.lines = follow('stocklog.csv'): Эта строка вызывает функциюfollowс именем файлаstocklog.csv. Функцияfollowвозвращает генератор, который выдает новые строки по мере их добавления в файл.rows = csv.reader(lines): Функцияcsv.reader()принимает строки, сгенерированные функциейfollow, и разбирает их на строки данных в формате CSV.- Цикл
forпроходит по этим строкам и выводит каждую из них.
Шаг 4: Проверьте вывод
После выполнения кода вы должны увидеть вывод, похожий на следующий (ваши данные могут отличаться):
['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']
...
Этот вывод показывает, что вы успешно создали конвейер обработки данных. Функция follow() генерирует строки из файла, а затем эти строки передаются функции csv.reader(), которая разбирает их на строки данных.
Если вы видите достаточно вывода, вы можете остановить выполнение, нажав Ctrl+C.
Что происходит?
Разберем, что происходит в этом конвейере:
follow('stocklog.csv')создает генератор. Этот генератор отслеживает файлstocklog.csvи выдает новые строки по мере их добавления в файл.csv.reader(lines)принимает строки, сгенерированные функциейfollow, и разбирает их на строки данных в формате CSV. Он понимает структуру файлов в формате CSV и разделяет строки на отдельные значения.- Затем цикл
forпроходит по этим строкам, выводя каждую из них. Это позволяет вам видеть данные в удобочитаемом формате.
Это простой пример конвейера обработки данных с использованием генераторов. В следующих шагах мы создадим более сложные и полезные конвейеры.
Создание класса Ticker
При обработке данных работа с сырыми данными может быть весьма сложной. Чтобы сделать нашу работу с данными о ценах на акции более организованной и эффективной, мы определим соответствующий класс для представления котировок акций. Этот класс станет шаблоном для наших данных о ценах на акции, сделав наш конвейер обработки данных более надежным и легким в управлении.
Создание файла ticker.py
Сначала нам нужно создать новый файл в WebIDE. Вы можете сделать это, нажав на иконку "New File" или щелкнув правой кнопкой мыши в проводнике файлов и выбрав "New File". Назовите этот файл
ticker.py. В этом файле будет находиться код нашего классаTicker.Теперь добавим следующий код в только что созданный файл
ticker.py. Этот код определит наш классTickerи настроит простой конвейер обработки данных для его тестирования.
## 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)
- После добавления кода сохраните файл. Вы можете сделать это, нажав
Ctrl+Sили выбрав "File" → "Save" в меню. Сохранение файла гарантирует, что ваши изменения будут сохранены и можно будет запустить код позже.
Понимание кода
Рассмотрим, что делает этот код пошагово:
В начале кода мы импортируем класс
Structureи типы полей из модуляstructure.py. Этот модуль уже настроен для вас. Эти импорты важны, так как они предоставляют строительные блоки для нашего классаTicker. КлассStructureстанет базовым классом для нашего классаTicker, а типы полей, такие какString,FloatиInteger, определят типы данных полей наших данных о ценах на акции.Затем мы определяем класс
Ticker, который наследуется отStructure. Этот класс имеет несколько полей, которые представляют различные аспекты данных о ценах на акции:name: Это поле хранит тикер акции, например, "IBM" или "AAPL". Оно помогает нам определить, акции какой компании мы обрабатываем.price: Оно хранит текущую цену акции. Это важная информация для инвесторов.dateиtime: Эти поля показывают, когда была сгенерирована котировка акции. Знание времени и даты важно для анализа тенденций изменения цен на акции в течение времени.change: Это представляет изменение цены акции. Оно показывает, выросла ли цена акции или упала по сравнению с предыдущим значением.open,high,low: Эти поля представляют цену открытия, максимальную цену и минимальную цену акции за определенный период. Они дают нам представление о диапазоне цен акции.volume: Это поле хранит количество проданных акций. Высокий объем торгов может указывать на сильный интерес рынка к определенной акции.
В блоке
if __name__ == '__main__':мы настраиваем конвейер обработки данных. Этот блок кода будет выполнен, когда мы запустим файлticker.pyнапрямую.follow('stocklog.csv')- это функция, которая генерирует строки из файлаstocklog.csv. Она позволяет нам читать файл построчно.csv.reader(lines)принимает эти строки и разбирает их на строки данных. CSV (Comma - Separated Values) - это распространенный формат файлов для хранения табличных данных, и эта функция помогает нам извлечь данные из каждой строки.(Ticker.from_row(row) for row in rows)- это выражение - генератор. Оно принимает каждую строку данных и преобразует ее в объектTicker. Таким образом, мы преобразуем сырые данные в формате CSV в структурированные объекты, с которыми легче работать.- Цикл
forпроходит по этим объектамTickerи выводит каждый из них. Это позволяет нам увидеть структурированные данные в действии.
Запуск кода
Запустим код, чтобы увидеть, как он работает:
Сначала убедимся, что мы находимся в директории проекта в терминале. Если вы еще не там, используйте следующую команду, чтобы перейти в нее:
cd /home/labex/projectКогда вы находитесь в правильной директории, запустите скрипт
ticker.pyс помощью следующей команды:python3 ticker.pyПосле запуска скрипта вы должны увидеть вывод, похожий на следующий (ваши данные могут отличаться):
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)
Вы можете остановить выполнение скрипта, нажав Ctrl+C, когда увидите достаточно вывода.
Обратите внимание, как сырые данные в формате CSV были преобразованы в структурированные объекты Ticker. Это преобразование делает данные намного легче обрабатывать в нашем конвейере обработки данных, так как теперь мы можем обращаться к данным о ценах на акции и манипулировать ими с помощью полей, определенных в классе Ticker.
Создание более сложного конвейера обработки данных
Теперь мы возьмем наш конвейер обработки данных на новый уровень, добавив фильтрацию и улучшив представление данных. Это облегчит анализ и понимание информации, с которой мы работаем. Мы внесем изменения в наш скрипт ticker.py. Фильтрация данных поможет нам сосредоточиться на конкретной информации, которая нас интересует, а представление ее в хорошо отформатированной таблице сделает ее более читаемой.
Обновление файла ticker.py
Сначала откройте файл
ticker.pyв WebIDE. WebIDE - это инструмент, который позволяет писать и редактировать код прямо в браузере. Он предоставляет удобную среду для внесения изменений в ваши Python - скрипты.Затем нам нужно заменить блок
if __name__ == '__main__':в файлеticker.pyследующим кодом. Этот блок кода является точкой входа в наш скрипт, и, заменив его, мы изменим, как скрипт обрабатывает и отображает данные.
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)
- После внесения этих изменений сохраните файл. Вы можете сделать это, нажав
Ctrl+Sна клавиатуре или выбрав "File" → "Save" в меню. Сохранение файла гарантирует, что ваши изменения будут сохранены и можно будет запустить код позже.
Понимание усовершенствованного конвейера
Рассмотрим более подробно, что делает этот усовершенствованный конвейер. Понимание каждого шага поможет вам увидеть, как разные части кода работают вместе для обработки и отображения данных.
Мы начинаем с импорта функций
create_formatterиprint_tableиз модуляtableformat. Этот модуль уже настроен для вас, и он предоставляет функции, которые помогают нам форматировать и выводить данные в красивой таблице.Затем мы создаем текстовый форматер с помощью
create_formatter('text'). Этот форматер будет использоваться для форматирования данных таким образом, чтобы они были легко читаемыми.Теперь разберем конвейер пошагово:
follow('stocklog.csv')- это функция, которая генерирует строки из файлаstocklog.csv. Она постоянно отслеживает файл на предмет появления новых данных и предоставляет строки по одной.csv.reader(lines)принимает строки, сгенерированные функциейfollow, и разбирает их на строки данных. Это необходимо, так как данные в файле CSV находятся в текстовом формате, и нам нужно преобразовать их в структурированный формат, с которым мы можем работать.(Ticker.from_row(row) for row in rows)- это выражение - генератор, которое преобразует каждую строку данных в объектTicker. ОбъектTickerпредставляет акцию и содержит информацию, такую как название акции, цена и изменение цены.(rec for rec in records if rec.change < 0)- это еще одно выражение - генератор, которое фильтрует объектыTicker. Оно сохраняет только те объекты, у которых изменение цены акции отрицательное. Это позволяет нам сосредоточиться на акциях, чья цена снизилась.print_table(negative, ['name', 'price', 'change'], formatter)принимает отфильтрованные объектыTickerи форматирует их в таблицу с помощью форматера, который мы создали ранее. Затем он выводит таблицу в консоль.
Этот конвейер демонстрирует мощь генераторов. Вместо того чтобы загружать все данные из файла в память сразу, мы объединяем несколько операций (чтение, разбор, преобразование, фильтрация) и обрабатываем данные по одному элементу за раз. Это экономит память и делает код более эффективным.
Запуск усовершенствованного конвейера
Запустим обновленный код, чтобы увидеть результаты.
Сначала убедитесь, что вы находитесь в директории проекта в терминале. Если вы еще не там, вы можете перейти в нее с помощью следующей команды:
cd /home/labex/projectКогда вы находитесь в директории проекта, запустите скрипт
ticker.pyс помощью следующей команды:python3 ticker.pyПосле запуска скрипта вы должны увидеть хорошо отформатированную таблицу в терминале. Эта таблица показывает только акции с отрицательным изменением цены.
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
Если вы видите достаточно вывода и хотите остановить выполнение скрипта, вы можете нажать Ctrl+C на клавиатуре.
Мощь конвейеров на основе генераторов
То, что мы создали здесь, представляет собой мощный конвейер обработки данных. Сводим его действия:
- Он постоянно отслеживает файл
stocklog.csvна предмет появления новых данных. Это означает, что по мере добавления новых данных в файл конвейер автоматически обработает их. - Он разбирает данные в формате CSV из файла в структурированные объекты
Ticker. Это облегчает работу с данными и выполнение операций над ними. - Он фильтрует данные на основе определенного критерия, в данном случае - отрицательного изменения цены. Это позволяет нам сосредоточиться на акциях, которые теряют в цене.
- Он форматирует и представляет отфильтрованные данные в читаемой таблице. Это облегчает анализ данных и вывод выводов.
Одно из ключевых преимуществ использования генераторов в этом конвейере - это минимальное использование памяти. Генераторы создают значения по запросу, что означает, что они не хранят все данные в памяти сразу. Это похоже на Unix - конвейеры, где каждый компонент обрабатывает данные и передает их следующему компоненту.
Вы можете думать о генераторах как о деталях Lego. Как вы можете собирать детали Lego вместе, чтобы создать разные конструкции, так вы можете комбинировать генераторы, чтобы создать мощные рабочие процессы обработки данных. Этот модульный подход позволяет создавать сложные системы из простых, повторно используемых компонентов.
Резюме
В этом практическом занятии вы научились использовать генераторы Python для создания эффективных конвейеров обработки данных. Вы выполнили несколько важных задач, таких как использование функции follow() для отслеживания файла на предмет появления новых данных, создание класса Ticker для представления котировок акций и построение многоэтапного конвейера обработки, который читает, разбирает и фильтрует данные в формате CSV, а затем форматирует и отображает результаты.
Подход на основе генераторов имеет несколько преимуществ, в том числе эффективное использование памяти, так как данные обрабатываются по запросу, модульность, позволяющая легко комбинировать и повторно использовать компоненты конвейера, и простота в выражении сложных потоков данных. Эти концепции широко применяются в реальной обработке данных, особенно для больших наборов данных или потоковых данных.