Для тех, кто не знает, Гамильтон — это микрофреймворк общего назначения для спецификации потоков данных, например. указание преобразований Pandas. Это поможет вам структурировать вашу кодовую базу и улучшить ваш код, например. вы всегда пишете модульный тестируемый код преобразования с Гамильтоном. Это достигается за счет введения парадигмы, в которой функции должны быть написаны в самоуверенной, декларативной манере. См. этот пост TDS для более подробного ознакомления.

Одним из последствий использования Hamilton для разработки является то, что он заставляет вас с самого начала превращать ваши функции Python в модули. Если итерация в записной книжке — ваш способ разработки, то может показаться трудным использовать Hamilton в настройках записной книжки. В этом посте я объясню, как вы можете повторять свою работу с Hamilton DAG, не выходя из своего ноутбука.

Шаг 1 — Установите Jupyter и Hamilton

Я предполагаю, что вы уже настроили этот шаг. Но на всякий случай:

pip install notebook
pip install sf-hamilton

Затем, чтобы запустить сервер ноутбука, это должно быть просто:

jupyter notebook

Шаг 2 — Настройте файлы

  1. Запустите блокнот Jupyter.
  2. Перейдите в каталог, в котором вы хотите разместить свой ноутбук и функциональные модули Hamilton.
  3. Создайте файл(ы) Python. Для этого перейдите в «Новый › текстовый файл». Откроется вид редактора «файл». Назовите файл и дайте ему расширение .py. Как только вы сохраните его, вы увидите, что Jupyter теперь обеспечивает подсветку синтаксиса Python. Держите эту вкладку открытой, чтобы вы могли вернуться к ней, чтобы отредактировать этот файл.
  4. Запустите блокнот, который вы будете использовать в другой вкладке браузера.

Шаг 3 — Основной процесс итерации

На высоком уровне вы будете переключаться между вкладками. Вы добавите функции в модуль python функций Hamilton, а затем импортируете/повторно импортируете этот модуль в свою записную книжку, чтобы получить изменения. Оттуда вы будете использовать Hamilton, как обычно, для запуска и выполнения вещей, а блокнот — для всех стандартных задач, для которых вы используете блокноты.

Давайте рассмотрим пример.

Вот функция, которую я добавил в наш функциональный модуль Гамильтона. Я назвал модуль some_functions.py (очевидно, выберите лучшее имя для вашей ситуации).

import pandas as pd
def avg_3wk_spend(spend: pd.Series) -> pd.Series:
    """Rolling 3 week average spend."""
    print("foo") # will use this to prove it reloaded!
    return spend.rolling(3).mean()

И вот что я настроил в своей записной книжке, чтобы иметь возможность использовать Hamilton и импортировать этот модуль:

Ячейка 1: это просто импорт базовых вещей, которые нам нужны.

import importlib
import pandas as pd
from hamilton import driver

Ячейка 2: импортируйте функциональные модули Hamilton.

# import your hamilton function module(s) here
import some_functions

Ячейка 3. Запускайте эту ячейку каждый раз, когда вносите изменения, и сохраняйте их в some_functions.py.

# use this to reload the module after making changes to it.
importlib.reload(some_functions)

Что это сделает, так это перезагрузит модуль и, следовательно, убедитесь, что код обновлен для использования.

Ячейка 4: использовать Гамильтон

config = {}
dr = driver.Driver(config, some_functions)
input_data = {'spend': pd.Series([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])}
df = dr.execute(['avg_3wk_spend'], inputs=input_data)

Вы должны увидеть foo в качестве вывода после запуска этой ячейки.

Итак, давайте теперь скажем, что мы повторяем наши функции Гамильтона. Перейдите к функциональному модулю Hamilton (в данном примере some_functions.py) на другой вкладке браузера и измените print("foo") на что-то другое, например. print("foo-bar"). Сохраните файл — он должен выглядеть примерно так:

def avg_3wk_spend(spend: pd.Series) -> pd.Series:
    """Rolling 3 week average spend."""
    print("foo-bar")
    return spend.rolling(3).mean()

Вернитесь к своему ноутбуку и повторно запустите Cell 3 и Cell 4. Теперь вы должны увидеть другой напечатанный вывод, например. foo-bar .

Поздравляем! Вам только что удалось повторить работу с Гамильтоном, используя блокнот Jupyter!

Подводя итог, вот как все выглядело с моей стороны:

  • Вот как выглядит мой файл some_functions.py:

  • Вот как выглядит мой блокнот:

Справка: я использую Google Colab и не могу сделать вышеперечисленное

Начиная с выпуска 1.8.0, теперь у вас есть возможность встроенного определения функций с вашим драйвером, которые можно использовать для создания DAG. Мы настоятельно рекомендуем использовать этот подход только в случае крайней необходимости — таким образом очень легко создавать спагетти-код.

Например, предположим, что мы хотим добавить функцию для вычисления логарифма avg_3wk_spend, а не добавлять его к some_functions.py, мы можем выполнить следующие шаги непосредственно в нашей записной книжке:

# Step 1 - define function
import numpy as np
def log_avg_3wk_spend(avg_3wk_spend: pd.Series) -> pd.Series:
    “””Simple function taking the logarithm of spend over signups.”””
    return np.log(avg_3wk_spend)

Затем нам нужно создать «временный модуль python», чтобы разместить его. Мы делаем это, импортируя ad_hoc_utils, а затем вызывая функцию create_temporary_module, передавая нужные функции и предоставляя имя для модуля, который мы создаем.

# Step 2 - create a temporary module to house all notebook functions
from hamilton import ad_hoc_utils
temp_module = ad_hoc_utils.create_temporary_module(
     log_avg_3wk_spend, module_name='function_example')

Теперь вы можете обращаться с temp_module как с модулем Python, передавать его вашему драйверу и использовать Hamilton как обычно:

# Step 3 - add the module to the driver and continue as usual
dr = driver.Driver(config, some_functions, temp_module) 
df = dr.execute(['avg_3wk_spend', 'log_avg_3wk_spend'], inputs=input_data)

Предостережение с этим подходом:

Использование «временного модуля Python» не позволит масштабировать вычисления с помощью Ray, Dask или Pandas в Spark. Поэтому мы предлагаем использовать этот подход только в целях разработки.

Совет: вы можете напрямую импортировать функции

Преимущество принудительного включения функций Гамильтона в модуль заключается в том, что их очень легко повторно использовать в другом контексте. Например. другой блокнот или напрямую.

Например, легко использовать функции записной книжки напрямую, например так:

some_functions.avg_3wk_spend(pd.Series([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))

Что вызывает функцию avg_3wk_spend, которую мы определили в модуле some_functions.py.

Совет: вы можете использовать магию ipython для автоматической перезагрузки кода.

Откройте модуль Python и блокнот Jupyter рядом друг с другом, а затем добавьте в блокнот %autoreload ipython magic для автоматической перезагрузки ячейки:

from hamilton.driver import Driver

# load extension
%load_ext autoreload
# configure autoreload to only affect specified files
%autoreload 1  
# import & specify my_module to be reloaded 
# i.e. this is the data transformation module that I have open in other tab
%aimport my_module  

hamilton_driver = Driver({}, my_module)
hamilton_driver.execute(['desired_output1', 'desired_output2'])

Затем вы должны следовать следующему процессу:

  1. Напишите свое преобразование данных в открытом модуле Python.
  2. В записной книжке создайте экземпляр драйвера Hamilton и протестируйте DAG с небольшим подмножеством данных.
  3. Из-за %autoreload модуль повторно импортируется с последними изменениями при каждом выполнении Hamilton DAG. Такой подход предотвращает неупорядоченное выполнение записных книжек, а функции всегда находятся в чистых файлах .py.

Кредит: Пост в блоге Тьерри Жана для этого последнего совета.

В заключение

Спасибо, что прочитали этот пост. Мы бы хотели, чтобы вы успешно использовали Hamilton. Не стесняйтесь оставлять вопросы/комментарии в нашем репозитории github (мы бы тоже хотели ⭐️!), или присоединяйтесь к нам на нашем слабом сервере, чтобы попросить о помощи или предложить предложения/улучшения.