Documentos de Académico
Documentos de Profesional
Documentos de Cultura
bas harenslak
Julián de Ruiter
MANEJO
Machine Translated by Google
Representa una
tarea/operación Canalización como DAG
Tarea 2
Tarea 1 Tarea 4
Tarea 3
archivo DAG
(Pitón)
Intervalo de programación = @daily
Canalizaciones de
datos con Apache Airflow
BAS HARENSLAK
Y JULIÁN DE RUITER
MANEJO
ISLA REFUGIO
Machine Translated by Google
Para obtener información en línea y solicitar este y otros libros de Manning, visite
www.manning.com. La editorial ofrece descuentos en este libro cuando se pide en cantidad.
Para obtener más información, póngase en contacto
Ninguna parte de esta publicación puede reproducirse, almacenarse en un sistema de recuperación o transmitirse de
ninguna forma o por medios electrónicos, mecánicos, fotocopiados o de otro modo, sin el permiso previo por escrito del
editor.
Muchas de las designaciones utilizadas por los fabricantes y vendedores para distinguir sus productos se reclaman
como marcas comerciales. Donde esas designaciones aparecen en el libro, y Manning Publications estaba al tanto de un
reclamo de marca registrada, las designaciones se han impreso en mayúsculas iniciales o en mayúsculas.
Reconociendo la importancia de preservar lo que se ha escrito, es política de Manning que los libros que publicamos se
impriman en papel libre de ácido, y realizamos nuestros mejores esfuerzos con ese fin.
Reconociendo también nuestra responsabilidad de conservar los recursos de nuestro planeta, los libros de Manning
están impresos en papel que es al menos 15 por ciento reciclado y procesado sin el uso de cloro elemental.
ISBN: 9781617296901
Impreso en los Estados Unidos de América
Machine Translated by Google
contenidos breves
PARTE 1 COMENZANDO ............................................... ..........1
1 ÿ Conoce Apache Airflow 3 2 ÿ
Anatomía de un DAG de Airflow 20 3 ÿ
Programación en Airflow 40 4 ÿ Plantillas
de tareas usando el contexto de Airflow 60 5 ÿ Definición
de dependencias entre tareas 85
v
Machine Translated by Google
vi CONTENIDOS BREVES
contenido
prefacio xv
agradecimientos xvii sobre
este libro xix
sobre los autores xxiii
sobre la ilustración de portada xxiv
viii
Machine Translated by Google
viii CONTENIDO
3 Programación en Airflow 40
3.1 Un ejemplo: procesamiento de eventos de usuario 41
3.2 Ejecución a intervalos regulares 42
Definición de intervalos de programación 42 ÿ Intervalos basados en cron
44 Intervalos basados en frecuencia 46 3.3 Procesamiento incremental
de datos 46
Obtener eventos de forma incremental 46 ÿ Referencias de tiempo dinámicas
usando fechas de ejecución 48 ÿ Partición de sus datos 50
55 ÿ Idempotencia 57
CONTENIDO ix
X CONTENIDO
9 Prueba 186
9.1 Primeros pasos con las pruebas 187
Prueba de integridad de todos los DAG 187 ÿ Configuración de una
canalización de CI/ CD 193 ÿ Escritura de pruebas unitarias 195 ÿ
Estructura del proyecto Pytest 196 ÿ Prueba con archivos en el disco 201
CONTENIDO xi
xi CONTENIDO
CONTENIDO XIII
específicos de Azure 398 17.3 Ejemplo: clasificación de películas sin servidor con
xiv CONTENIDO
índice 445
Machine Translated by Google
prefacio
Ambos hemos tenido la suerte de ser ingenieros de datos en tiempos interesantes y desafiantes.
Para bien o para mal, muchas empresas y organizaciones se están dando cuenta de que los datos juegan un papel
papel clave en la gestión y mejora de sus operaciones. Desarrollos recientes en
El aprendizaje automático y la IA han abierto una gran cantidad de nuevas oportunidades para capitalizar.
Sin embargo, la adopción de procesos centrados en datos suele ser difícil, ya que generalmente requiere
coordinar trabajos a través de muchos sistemas heterogéneos diferentes y vincular todo
juntos de manera agradable y oportuna para el próximo análisis o implementación del producto.
En 2014, los ingenieros de Airbnb reconocieron los desafíos de administrar datos complejos
flujos de trabajo dentro de la empresa. Para hacer frente a esos desafíos, comenzaron a desarrollar
Airflow: una solución de código abierto que les permitió escribir y programar flujos de trabajo
y supervise las ejecuciones de flujo de trabajo utilizando la interfaz web integrada.
El éxito del proyecto Airflow condujo rápidamente a su adopción bajo Apache
Software Foundation, primero como un proyecto de incubadora en 2016 y luego como un proyecto de alto nivel en
2019. Como resultado, muchas grandes empresas ahora confían en Airflow para orquestar
numerosos procesos de datos críticos.
Trabajando como consultores en GoDataDriven, hemos ayudado a varios clientes a adoptar el flujo de aire como
un componente clave en proyectos que involucran la construcción de lagos/plataformas de datos,
modelos de aprendizaje automático, etc. Al hacerlo, nos dimos cuenta de que entregar estos
las soluciones pueden ser desafiantes, ya que las herramientas complejas como Airflow pueden ser difíciles de aprender
durante la noche. Por esta razón, también desarrollamos un programa de capacitación de Airflow en GoData Driven, y
organizamos y participamos con frecuencia en reuniones para compartir nuestros
conocimientos, vistas e incluso algunos paquetes de código abierto. Combinados, estos esfuerzos han
XV
Machine Translated by Google
xvi PREFACIO
nos ayudó a explorar las complejidades de trabajar con Airflow, que no siempre fueron fáciles
comprender utilizando la documentación que tenemos a nuestra disposición.
En este libro, nuestro objetivo es proporcionar una introducción completa a Airflow que cubra
todo, desde la creación de flujos de trabajo simples hasta el desarrollo de componentes personalizados y
diseñar/gestionar implementaciones de Airflow. Tenemos la intención de complementar muchos de los
excelentes blogs y otra documentación en línea al reunir varios temas en
un solo lugar, utilizando un formato conciso y fácil de seguir. Al hacerlo, esperamos impulsar
tus aventuras con Airflow construyendo sobre la experiencia que hemos ganado
a través de diversos desafíos en los últimos años.
Machine Translated by Google
expresiones de gratitud
Este libro no hubiera sido posible sin el apoyo de muchas personas increíbles.
Los colegas de GoDataDriven y amigos personales nos apoyaron y brindaron valiosas sugerencias
y puntos de vista críticos. Además, los lectores del Programa de acceso anticipado de Manning
(MEAP) publicaron comentarios útiles en el foro en línea.
Los revisores del proceso de desarrollo también contribuyeron con comentarios útiles: Al
Krinker, Clifford Thurber, Daniel Lamblin, David Krief, Eric Platon, Felipe Ortega, Jason Rendel,
Jeremy Chen, Jiri Pik, Jonathan Wood, Karthik Sirasanagandla, Kent R.
Spillner, Lin Chen, Philip Best, Philip Patterson, Rambabu Posa, Richard Meinsen, Robert G.
Gimbel, Roman Pavlov, Salvatore Campagna, Sebastián Palma Mardones, Thorsten Weber, Ursin
Stauss y Vlad Navitski.
En Manning, le debemos un agradecimiento especial a Brian Sawyer, nuestro editor de
adquisiciones, quien nos ayudó a dar forma a la propuesta inicial del libro y creyó en que
podríamos llevarlo a cabo; Tricia Louvar, nuestra editora de desarrollo, que fue muy paciente al
responder todas nuestras preguntas e inquietudes, brindó comentarios críticos sobre cada uno de
nuestros capítulos preliminares y fue una guía esencial para nosotros a lo largo de todo este viaje;
y al resto del personal también: Deirdre Hiam, nuestra editora de proyectos; Michele Mitchell,
nuestra correctora de estilo; Keri Hales, nuestra correctora; y Al Krinker, nuestro corrector técnico.
bas harenslak
Quisiera agradecer a mis amigos y familiares por su paciencia y apoyo durante esta aventura de
un año y medio que pasó de ser un proyecto paralelo a innumerables días, noches y fines de
semana. Stephanie, gracias por aguantarme siempre trabajando en
xvii
Machine Translated by Google
Julián de Ruiter
En primer lugar, quisiera agradecer a mi esposa, Anne Paulien, y a mi hijo, Dexter, por
su infinita paciencia durante las muchas horas que pasé haciendo “sólo un poco más
trabajo” en el libro. Este libro no hubiera sido posible sin su inquebrantable
apoyo. Del mismo modo, también me gustaría agradecer a nuestra familia y amigos por su
apoyo y confianza. Finalmente, me gustaría agradecer a nuestros colegas de GoDataDriven por su
consejos y aliento, de quien también he aprendido una cantidad increíble en el
años pasados.
Machine Translated by Google
xix
Machine Translated by Google
cómo se pueden crear utilizando Apache Airflow. También analiza las ventajas y desventajas de
Airflow en comparación con otras soluciones, incluidas las situaciones en las que es posible
que no desee usar Apache Airflow.
La Parte 2 profundiza en el uso de temas de Airflow más complejos, incluida la interfaz con sistemas
externos, la creación de sus propios componentes personalizados y el diseño de pruebas para sus
canalizaciones. ÿ El Capítulo 6 muestra cómo puede desencadenar flujos de trabajo de otras formas
que no impliquen
horarios fijos, como archivos que se cargan o mediante una llamada HTTP.
ÿ El Capítulo 7 demuestra los flujos de trabajo mediante el uso de operadores que organizan
varias tareas fuera de Airflow, lo que le permite desarrollar un flujo de eventos a través de
sistemas que no están conectados.
ÿ El Capítulo 8 explica cómo puede crear componentes personalizados para Airflow que le permitan
reutilizar la funcionalidad en todas las canalizaciones o integrarlos con sistemas que no son
compatibles con la funcionalidad integrada de Airflow. ÿ El Capítulo 9 analiza varias opciones
para probar los flujos de trabajo de Airflow, toca varias propiedades de los operadores y cómo
abordarlos durante la prueba. ÿ El Capítulo 10 demuestra cómo puede usar flujos de trabajo
basados en contenedores para ejecutar tareas de canalización dentro de Docker o Kubernetes y
analiza las ventajas y desventajas de estos enfoques basados en contenedores.
Machine Translated by Google
ÿ El Capítulo 11 destaca varias mejores prácticas para usar cuando se construyen tuberías, que
le ayudará a diseñar e implementar soluciones eficientes y mantenibles.
ÿ El Capítulo 12 detalla varios temas a tener en cuenta cuando se ejecuta Airflow en un entorno de
producción, como arquitecturas para escalar, monitorear, registrar y
alertando
ÿ El Capítulo 13 analiza cómo asegurar su instalación de Airflow para evitar
acceso y minimizar el impacto en caso de que se produzca una vulneración.
ÿ El Capítulo 14 muestra un ejemplo de proyecto Airflow en el que periódicamente
procesar viajes de Yellow Cab y Citi Bikes de la ciudad de Nueva York para determinar el
medio de transporte más rápido entre barrios.
La Parte 4 explora cómo ejecutar Airflow en varias plataformas en la nube e incluye temas como
como diseñar implementaciones de Airflow para las diferentes nubes y cómo usar
operadores para interactuar con diferentes servicios en la nube.
ÿ El Capítulo 15 brinda una introducción general al describir qué componentes de Airflow están involucrados
en las implementaciones (en la nube), presenta la idea detrás de los componentes específicos de la
nube integrados en Airflow y sopesa las opciones de implementación.
su propia implementación en la nube frente al uso de una solución administrada.
ÿ El Capítulo 16 se enfoca en la plataforma en la nube AWS de Amazon, y amplía el capítulo anterior al
diseñar soluciones de implementación para Airflow en AWS y demostrar cómo se pueden usar
componentes específicos para aprovechar los servicios de AWS. ÿ El Capítulo 17 diseña
implementaciones y demuestra componentes específicos de la nube
para la plataforma Azure de Microsoft.
ÿ El Capítulo 18 aborda las implementaciones y los componentes específicos de la nube para Google
plataforma GCP.
Las personas nuevas en Airflow deben leer los capítulos 1 y 2 para tener una buena idea de lo que Airflow
es y lo que puede hacer. Los capítulos 3 a 5 brindan información importante sobre la clave de Airflow
funcionalidad. El resto del libro trata temas como la creación de componentes personalizados, las pruebas, las
prácticas recomendadas y las implementaciones, y puede leerse desordenadamente, en función de
las necesidades particulares del lector.
sobre el código
Todo el código fuente en las listas o el texto está en una fuente de ancho fijo como esta para separarlo
del texto ordinario. A veces, el código también está en negrita para resaltar el código que ha cambiado
de pasos anteriores en el capítulo, como cuando se agrega una nueva función a una línea existente
de código
marcadores (ÿ). Además, los comentarios en el código fuente a menudo se eliminan de las listas cuando el
código se describe en el texto. Las anotaciones de código acompañan a muchos de los listados, destacando
conceptos importantes.
Referencias a elementos en el código, scripts o clases/variables/
los valores suelen estar en cursiva para ayudar a distinguirlos del texto que los rodea.
El código fuente de todos los ejemplos y las instrucciones para ejecutarlos con Docker y Docker
Compose están disponibles en nuestro repositorio de GitHub (https://github.com/BasPH/ data-pipelines-with-
apache-airflow) y se puede descargar a través del sitio web del libro (www.manning.com/books/data-
pipelines-with-apache-airflow).
NOTA El Apéndice A proporciona instrucciones más detalladas sobre cómo ejecutar los ejemplos
de código.
Todos los ejemplos de código se han probado con Airflow 2.0. La mayoría de los ejemplos también deberían
ejecutarse en versiones anteriores de Airflow (1.10), con pequeñas modificaciones. Siempre que fue posible,
hemos incluido indicadores en línea sobre cómo hacerlo. Para ayudarlo a tener en cuenta las diferencias
en las rutas de importación entre Airflow 2.0 y 1.10, el apéndice B proporciona una descripción general de
las rutas de importación modificadas entre las dos versiones.
El compromiso de Manning con nuestros lectores es proporcionar un lugar donde pueda tener lugar un
diálogo significativo entre lectores individuales y entre lectores y autores. No se trata de un compromiso de
participación específica por parte de los autores, cuya contribución al foro es voluntaria (y no remunerada).
¡Le sugerimos que intente hacerles algunas preguntas desafiantes a los autores para que su interés no se
desvíe!
El foro y los archivos de debates anteriores estarán accesibles desde el sitio web del editor mientras el
libro esté impreso.
Machine Translated by Google
XXIII
Machine Translated by Google
XXIV
Machine Translated by Google
Parte 1
Empezando
Este parte del libro preparará el escenario para su viaje hacia la creación de conductos para todo
tipo de maravillosos procesos de datos utilizando Apache Airflow. El primero
dos capítulos tienen como objetivo brindarle una descripción general de qué es Airflow y qué
puede hacer por ti.
Primero, en el capítulo 1, exploraremos los conceptos de canalizaciones de datos y esbozaremos los
El papel que juega Apache Airflow para ayudarlo a implementar estas canalizaciones. Para establecer
expectativas, también compararemos Airflow con varias otras tecnologías y discutiremos cuándo podría o
no ser una buena opción para su caso de uso específico. Próximo,
el capítulo 2 le enseñará cómo implementar su primera canalización en Airflow. Después
construyendo la canalización, también examinaremos cómo ejecutar esta canalización y monitorear
su progreso utilizando la interfaz web de Airflow.
Los capítulos 3 a 5 profundizan en los conceptos clave de Airflow para brindarle una sólida
comprensión de los fundamentos de Airflow.
El Capítulo 3 se centra en la semántica de programación, que le permite configurar el flujo de aire para
ejecutar sus canalizaciones a intervalos regulares. Esto le permite (por ejemplo) escribir
canalizaciones que cargan y procesan datos de manera eficiente en forma diaria, semanal o mensual
base. A continuación, en el capítulo 4, analizaremos los mecanismos de creación de plantillas en Airflow, que
le permite hacer referencia dinámicamente a variables como las fechas de ejecución en su
tuberías Finalmente, en el capítulo 5, nos sumergiremos en diferentes enfoques para definir
dependencias de tareas en sus canalizaciones, que le permiten definir tareas complejas
jerarquías, incluidas tareas condicionales, ramas, etc.
Si es nuevo en Airflow, le recomendamos que se asegure de comprender las
conceptos principales descritos en los capítulos 3 a 5, ya que estos son clave para usarlo de manera efectiva.
Machine Translated by Google
Las personas y las empresas se basan cada vez más en los datos y desarrollan canalizaciones de
datos como parte de sus actividades comerciales diarias. Volúmenes de datos involucrados en estos
Los procesos comerciales han aumentado sustancialmente a lo largo de los años, de megabytes por
día a gigabytes por minuto. Aunque manejar este diluvio de datos puede parecer una
desafío considerable, estos crecientes volúmenes de datos se pueden gestionar con el
utillaje apropiado.
Este libro se centra en Apache Airflow, un marco orientado a lotes para crear
canalizaciones de datos. La característica clave de Airflow es que le permite crear fácilmente
canalizaciones de datos utilizando un marco flexible de Python, al mismo tiempo que proporciona muchas construcciones
bloques que le permiten unir las diferentes tecnologías encontradas
en los paisajes tecnológicos modernos.
3
Machine Translated by Google
Airflow se considera mejor como una araña en una red: se encuentra en medio de sus procesos de datos y
coordina el trabajo que se lleva a cabo en los diferentes sistemas (distribuidos). Como
Por lo tanto, Airflow no es una herramienta de procesamiento de datos en sí misma, sino que orquesta los
diferentes componentes responsables de procesar sus datos en canalizaciones de datos.
En este capítulo, primero le daremos una breve introducción a las canalizaciones de datos en Apache.
Flujo de aire. Luego, discutiremos varias consideraciones a tener en cuenta al evaluar si Airflow es adecuado
para usted y demostraremos cómo dar los primeros pasos con
Flujo de aire.
Obtener y
datos limpios Figura 1.1 Descripción general del caso de uso del
panel meteorológico, en el que los datos meteorológicos
API de DashboardWeather se obtienen de una API externa y se introducen en un panel dinámico
Como puede ver, esta tubería relativamente simple ya consta de tres tareas diferentes
que cada uno realice una parte del trabajo. Además, estas tareas deben ejecutarse en un
orden específico, ya que (por ejemplo) no tiene sentido intentar transformar los datos
antes de ir a buscarlo. Del mismo modo, no podemos enviar ningún dato nuevo al tablero hasta que haya
sufrido las transformaciones requeridas. Como tal, debemos asegurarnos de que este
el orden de tareas implícito también se aplica cuando se ejecuta este proceso de datos.
Una forma de hacer que las dependencias entre tareas sean más explícitas es dibujar la tubería de datos como
un gráfico. En esta representación basada en gráficos, las tareas se representan como nodos en
el gráfico, mientras que las dependencias entre tareas están representadas por bordes dirigidos
entre los nodos de tareas. La dirección del borde indica la dirección del
dependencia, con un borde que apunta de la tarea A a la tarea B, lo que indica que la tarea A necesita
debe completarse antes de que la tarea B pueda comenzar. Tenga en cuenta que este tipo de gráfico generalmente se llama
un gráfico dirigido, debido a las direcciones en los bordes del gráfico.
Al aplicar esta representación gráfica a nuestra canalización del tablero meteorológico, podemos ver
que el gráfico proporciona una representación relativamente intuitiva de la canalización general
Machine Translated by Google
(figura 1.2). Con solo echar un vistazo rápido al gráfico, podemos ver que nuestra canalización consta de tres
tareas diferentes, cada una de las cuales corresponde a una de las tareas descritas. Otro
que esto, la dirección de los bordes indica claramente el orden en que las tareas necesitan
para ser ejecutado: simplemente podemos seguir las flechas para rastrear la ejecución.
Leyenda
Este tipo de gráfico generalmente se denomina gráfico acíclico dirigido (DAG), ya que el gráfico contiene bordes
dirigidos y no contiene bucles ni ciclos (acíclico). Esta propiedad acíclica es extremadamente importante, ya que
evita que nos topemos con dependencias circulares.
(figura 1.3) entre tareas (donde la tarea A depende de la tarea B y viceversa). Estas dependencias circulares se
vuelven problemáticas cuando intentamos ejecutar el gráfico, ya que ejecutamos
en una situación en la que la tarea 2 solo puede ejecutarse una vez que se ha completado la tarea 3, mientras que
la tarea 3 solo puede ejecutarse una vez que se haya completado la tarea 2. Esta contradicción lógica
conduce a un tipo de situación de interbloqueo, en la que ni la tarea 2 ni la 3 pueden ejecutarse, lo que impide
impedir que ejecutemos el gráfico.
Tenga en cuenta que esta representación es diferente de las representaciones gráficas cíclicas, que pueden
contienen ciclos para ilustrar partes iterativas de algoritmos (por ejemplo), como son comunes
Machine Translated by Google
en muchas aplicaciones de aprendizaje automático. Sin embargo, Airflow (y muchos otros administradores
de flujo de trabajo) utilizan la propiedad acíclica de los DAG para resolver y ejecutar de manera eficiente
estos gráficos de tareas.
Una buena propiedad de esta representación DAG es que proporciona un algoritmo relativamente sencillo
que podemos usar para ejecutar la canalización. Conceptualmente, este algoritmo consta de los siguientes
pasos:
Para ver cómo funciona esto, analicemos una pequeña ejecución de nuestro canal de control (figura 1.4). En
nuestro primer ciclo a través de los pasos de nuestro algoritmo, vemos que las tareas de limpieza y envío
aún dependen de las tareas anteriores que aún no se han completado. Como tal, las dependencias de estas
tareas no se han satisfecho, por lo que en este momento no se pueden agregar a la cola de ejecución. Sin
embargo, la tarea de búsqueda no tiene aristas entrantes, lo que significa que no tiene dependencias
ascendentes insatisfechas y, por lo tanto, se puede agregar a la cola de ejecución.
Después de completar la tarea de búsqueda , podemos iniciar el segundo ciclo examinando las
dependencias de las tareas de limpieza y envío . Ahora vemos que la tarea de limpieza se puede ejecutar
ya que su dependencia ascendente (la tarea de búsqueda ) se ha completado. Como tal, podemos agregar
la tarea a la cola de ejecución. La tarea de inserción no se puede agregar a la cola, ya que depende de la
tarea de limpieza , que aún no hemos ejecutado.
En el tercer ciclo, después de completar la tarea de limpieza , la tarea de inserción finalmente está lista
para su ejecución, ya que ahora se ha satisfecho su dependencia anterior de la tarea de limpieza . Como
resultado, podemos agregar la tarea a la cola de ejecución. Una vez que la tarea de inserción ha terminado
de ejecutarse, no nos quedan más tareas por ejecutar, por lo que finaliza la ejecución de la canalización
general.
Aunque la representación gráfica de una tubería proporciona una descripción general intuitiva de las tareas
en la tubería y sus dependencias, es posible que se pregunte por qué no usaríamos un script simple para
ejecutar esta cadena lineal de tres pasos. Para ilustrar algunas ventajas del enfoque basado en gráficos,
pasemos a un ejemplo un poco más grande.
En este nuevo caso de uso, se nos acercó el propietario de una empresa paraguas,
Machine Translated by Google
Obtener pronóstico del tiempo Limpiar datos de pronóstico Enviar datos al tablero
Bucle 2 La tarea ha terminado Tarea ahora lista para ejecución, No está listo para la ejecución
ejecución como su dependencia aguas arriba aún; todavía tiene insatisfecho
Está satisfecho dependencias
Obtener pronóstico del tiempo Limpiar datos de pronóstico dEnviar datos al tablero
Obtener pronóstico del tiempo Limpiar datos de pronóstico Enviar datos al tablero
Estado final
Leyenda
Figura 1.4 Uso de la estructura DAG para ejecutar tareas en la canalización de datos en el orden
correcto: representa el estado de cada tarea durante cada uno de los bucles a través del algoritmo, lo
que demuestra cómo esto conduce a la ejecución completa de la canalización (estado final)
Obtener y
API meteorológica limpiar datos
Figura 1.5 Descripción general del caso de uso de la demanda global, en el que se utilizan datos meteorológicos
y de ventas históricos para entrenar un modelo que predice demandas de ventas futuras en función de las
previsiones meteorológicas
se puede usar como entrada para crear un modelo de aprendizaje automático predictivo.
Esta canalización se puede representar usando la misma representación basada en gráficos que usamos antes, dibujando tareas
Una diferencia importante con nuestro ejemplo anterior es que los primeros pasos de esta canalización (obtener y borrar los
datos meteorológicos/de ventas) son, de hecho, independientes entre sí, ya que involucran dos conjuntos de datos separados. Esto
se ilustra claramente con las dos ramas separadas en la representación gráfica de la tubería (figura 1.6), que se pueden ejecutar en
paralelo si aplicamos nuestro algoritmo de ejecución de gráficos, haciendo un mejor uso de los recursos disponibles y reduciendo
potencialmente el tiempo de ejecución de una tubería. en comparación con la ejecución de las tareas secuencialmente.
Entrenar Implementar
Unir conjuntos de datos
modelo ML modelo ML
Figura 1.6 Independencia entre las tareas de ventas y meteorológicas en la representación gráfica de la
canalización de datos para el modelo general de previsión de demanda. Los dos conjuntos de tareas de
recuperación/limpieza son independientes, ya que involucran dos conjuntos de datos diferentes (los conjuntos de datos meteorológicos y de ventas
Esta independencia está indicada por la falta de bordes entre los dos conjuntos de tareas.
Machine Translated by Google
Por supuesto, el desafío de ejecutar gráficos de tareas dependientes no es un problema nuevo en computación. A
lo largo de los años, muchas de las llamadas soluciones de "gestión del flujo de trabajo"
han sido desarrollados para abordar este problema, que generalmente le permiten definir y
ejecutar gráficos de tareas como flujos de trabajo o canalizaciones.
Algunos administradores de flujo de trabajo conocidos de los que puede haber oído hablar incluyen los que se enumeran
en la tabla 1.1.
Tabla 1.1 Descripción general de varios administradores de flujo de trabajo conocidos y sus características clave.
una. Algunas herramientas fueron creadas originalmente por (ex) empleados de una empresa; sin embargo, todas las herramientas son de código abierto y no están representadas por una
sola empresa.
b. La calidad y las características de las interfaces de usuario varían ampliamente.
C. https://github.com/bitphy/argo-cron.
Aunque cada uno de estos administradores de flujo de trabajo tiene sus propias fortalezas y debilidades,
todos brindan una funcionalidad central similar que le permite definir y ejecutar canalizaciones que contienen
múltiples tareas con dependencias.
Una de las diferencias clave entre estas herramientas es cómo definen sus flujos de trabajo.
Por ejemplo, herramientas como Oozie usan archivos estáticos (XML) para definir flujos de trabajo, que
proporciona flujos de trabajo legibles pero flexibilidad limitada. Otras soluciones como Luigi y
Machine Translated by Google
Airflow le permite definir flujos de trabajo como código, lo que proporciona una mayor flexibilidad pero
puede ser más difícil de leer y probar (dependiendo de las habilidades de codificación de la persona que
implementa el flujo de trabajo).
Otras diferencias clave radican en el alcance de las funciones proporcionadas por el administrador de flujo
de trabajo. Por ejemplo, herramientas como Make y Luigi no brindan soporte integrado para
programación de flujos de trabajo, lo que significa que necesitará una herramienta adicional como Cron si desea
ejecute su flujo de trabajo en un horario recurrente. Otras herramientas pueden proporcionar funciones
adicionales, como programación, supervisión, interfaces web fáciles de usar, etc.
la plataforma, lo que significa que no tiene que unir varias herramientas usted mismo
para obtener estas características.
En definitiva, elegir la solución de gestión de flujo de trabajo adecuada para sus necesidades
requieren una consideración cuidadosa de las características clave de las diferentes soluciones y
cómo se ajustan a sus necesidades. En la siguiente sección, nos sumergiremos en Airflow: el enfoque
de este libro, y explore varias características clave que lo hacen particularmente adecuado para
manejar flujos de trabajo o canalizaciones orientados a datos.
Al igual que otros administradores de flujos de trabajo, Airflow le permite definir canalizaciones o flujos de trabajo
como DAG de tareas. Estos gráficos son muy similares a los ejemplos esbozados en el
sección anterior, con tareas definidas como nodos en el gráfico y dependencias como
bordes dirigidos entre las tareas.
En Airflow, usted define sus DAG usando código de Python en archivos DAG, que son esencialmente
secuencias de comandos de Python que describen la estructura del DAG correspondiente. Como tal,
cada archivo DAG generalmente describe el conjunto de tareas para un DAG determinado y las dependencias
entre las tareas, que luego Airflow analiza para identificar la estructura DAG
(figura 1.7). Aparte de esto, los archivos DAG suelen contener algunos metadatos adicionales
sobre el DAG que le dice a Airflow cómo y cuándo debe ejecutarse, etc. Bien
profundice más en esta programación en la siguiente sección.
Una ventaja de definir Airflow DAG en código Python es que esta programática
El enfoque le brinda mucha flexibilidad para crear DAG. Por ejemplo, como nosotros
verá más adelante en este libro, puede usar el código de Python para generar dinámicamente opciones
tareas dependiendo de ciertas condiciones o incluso generar DAG completos basados en metadatos externos o
archivos de configuración. Esta flexibilidad brinda una gran cantidad de personalización.
en cómo construye sus tuberías, lo que le permite adaptar Airflow a sus necesidades de construcción
tuberías arbitrariamente complejas.
Machine Translated by Google
Representa una
tarea/operación Canalización como DAG
Tarea 2
Tarea 1 Tarea 4
Tarea 3
archivo DAG
(Pitón)
Intervalo de programación = @daily
Figura 1.7 Las canalizaciones de flujo de aire se definen como DAG mediante código Python
en archivos DAG. Cada archivo DAG normalmente define un DAG, que describe las
diferentes tareas y sus dependencias. Además de esto, el DAG también define un intervalo
de programación que determina cuándo Airflow ejecuta el DAG.
Además de esta flexibilidad, otra ventaja de la base Python de Airflow es que las tareas pueden
ejecutar cualquier operación que pueda implementar en Python. Con el tiempo, esto ha llevado al
desarrollo de muchas extensiones de Airflow que le permiten ejecutar tareas en una amplia variedad
de sistemas, incluidas bases de datos externas, tecnologías de big data y varios servicios en la
nube, lo que le permite crear canalizaciones de datos complejas que unen procesos de datos. a
través de muchos sistemas diferentes.
Almacén de metadatos
Tienda Ejecutar
serializada tareas
DAG
Programador Programar
de flujo de aire tareas
Cola
Leer
DAG
Figura 1.8 Descripción general de los principales componentes involucrados en Airflow (p. ej., el servidor web, el
programador y los trabajadores de Airflow)
Podría decirse que el corazón de Airflow es el programador, ya que aquí es donde sucede la mayor
parte de la magia que determina cuándo y cómo se ejecutan sus canalizaciones. En un nivel alto, el
planificador ejecuta los siguientes pasos (figura 1.9):
1 Una vez que los usuarios han escrito sus flujos de trabajo como DAG, el programador lee los
archivos que contienen estos DAG para extraer las tareas correspondientes, las dependencias
y el intervalo de programación de cada DAG.
2 Para cada DAG, el programador luego verifica si el intervalo de programación para el DAG ha
pasado desde la última vez que se leyó. Si es así, las tareas en el DAG están programadas
para su ejecución.
3 Para cada tarea programada, el programador verifica si las dependencias (= tareas previas)
de la tarea se han completado. Si es así, la tarea se agrega a la cola de ejecución.
El lector astuto habrá notado que los pasos seguidos por el planificador son, de hecho, muy similares
al algoritmo presentado en la sección 1.1. Esto no es por accidente, ya que
Machine Translated by Google
Si se satisfacen las
4. Monitores de usuario dependencias de la tarea
ejecución + tarea
resultados utilizando
Agregar tarea a
la interfaz web.
la cola de ejecución
Tienda
serializada
DAG
Almacén de metadatos
Figura 1.9 Resumen esquemático del proceso involucrado en el desarrollo y ejecución de canalizaciones como DAG
mediante Airflow
Airflow esencialmente sigue los mismos pasos, agregando algo de lógica adicional en la parte superior para manejar
su lógica de programación.
Una vez que las tareas se han puesto en cola para su ejecución, son recogidas por un grupo de trabajadores
de flujo de aire que ejecutan tareas en paralelo y realizan un seguimiento de sus resultados. Estos resultados se
comunican al metastore de Airflow para que los usuarios puedan realizar un seguimiento del progreso de las tareas
y ver sus registros mediante la interfaz web de Airflow (proporcionada por el servidor web de Airflow).
Tu nombre de usuario
+ contraseña
Figura 1.10 La página de inicio de sesión de la interfaz web de Airflow. En los ejemplos de código que acompañan
a este libro, se proporciona un usuario predeterminado "admin" con la contraseña "admin".
Figura 1.11 La página principal de la interfaz web de Airflow, que muestra una descripción general de los DAG
disponibles y sus resultados recientes
Machine Translated by Google
Figura 1.12 La vista de gráfico en la interfaz web de Airflow, que muestra una descripción general de las tareas en
un DAG individual y las dependencias entre estas tareas
Además de esta vista de gráfico, Airflow también proporciona una vista de árbol detallada que muestra todas las
ejecuciones históricas y en ejecución para el DAG correspondiente (figura 1.13). Este es posiblemente el
vista más potente proporcionada por la interfaz web, ya que le brinda una descripción general rápida de
cómo se ha desempeñado un DAG con el tiempo y le permite profundizar en las tareas fallidas para ver
Qué salió mal.
De forma predeterminada, Airflow puede manejar fallas en las tareas al volver a intentarlas un par de veces.
(opcionalmente con algún tiempo de espera en el medio), lo que puede ayudar a que las tareas se recuperen de cualquier
fallas intermitentes. Si los reintentos no ayudan, Airflow registrará la tarea como fallida,
notificando opcionalmente sobre la falla si está configurado para hacerlo. La depuración de tareas fallidas es bastante
sencilla, ya que la vista de árbol le permite ver qué tareas fallaron y
cavar en sus registros. La misma vista también le permite borrar los resultados de
tareas para volver a ejecutarlas (junto con cualquier tarea que dependa de esa tarea), permitiéndole
vuelva a ejecutar fácilmente cualquier tarea después de realizar cambios en su código.
dieciséis
CAPÍTULO 1 Conozca Apache Airflow
una tarea
Estado de un
sola tarea
una carrera de
un flujo de trabajo
Figura 1.13 Vista de árbol de Airflow, que muestra los resultados de varias ejecuciones del modelo de ventas generales
DAG (ejecuciones más recientes + históricas). Las columnas muestran el estado de una ejecución del DAG y las filas
muestran el estado de todas las ejecuciones de una sola tarea. Los colores (que puedes ver en la versión del libro
electrónico) indican el resultado de la tarea correspondiente. Los usuarios también pueden hacer clic en los "cuadrados"
de la tarea para obtener más detalles sobre una instancia de tarea determinada, o para restablecer el estado de una
tarea para que Airflow pueda volver a ejecutarla, si lo desea.
le permite dividir el tiempo en intervalos discretos (por ejemplo, todos los días, semanas, etc.), y ejecutar
su DAG para cada uno de estos intervalos.1
Esta propiedad de los intervalos de programación de Airflow es invaluable para implementar canalizaciones de datos
eficientes, ya que le permite crear canalizaciones de datos incrementales. En estos
canalizaciones incrementales, cada ejecución de DAG procesa solo datos durante el tiempo correspondiente
slot (el delta de los datos) en lugar de tener que volver a procesar todo el conjunto de datos cada vez.
Especialmente para conjuntos de datos más grandes, esto puede proporcionar importantes beneficios de tiempo y costo al
evitando costosos recálculos de los resultados existentes.
Los intervalos de programación se vuelven aún más poderosos cuando se combinan con el concepto
de reposición, que le permite ejecutar un nuevo DAG para intervalos de programación históricos
que ocurrió en el pasado. Esta característica le permite crear fácilmente (o rellenar) nuevos datos
conjuntos con datos históricos simplemente ejecutando su DAG para estos intervalos de programación anteriores.
Además, al borrar los resultados de ejecuciones anteriores, también puede usar esta función Airflow para
vuelva a ejecutar fácilmente cualquier tarea histórica si realiza cambios en su código de tarea, lo que le permite
para reprocesar fácilmente un conjunto de datos completo cuando sea necesario.
1
Si esto te suena un poco abstracto ahora, no te preocupes, ya que proporcionamos más detalles sobre estos conceptos más adelante en el
libro.
Machine Translated by Google
En las secciones anteriores, ya describimos varias características clave que hacen que Airflow
ideal para implementar canalizaciones de datos orientadas a lotes. En resumen, estos incluyen la
siguiendo:
ÿ La rica interfaz web de Airflow proporciona una vista fácil para monitorear los resultados de
su tubería se ejecuta y depura cualquier falla que pueda haber ocurrido.
Una ventaja adicional de Airflow es que es de código abierto, lo que garantiza que
puede construir su trabajo en Airflow sin quedarse bloqueado por ningún proveedor. Las soluciones de flujo de aire
administrado también están disponibles en varias compañías (si desea
algo de soporte técnico), lo que le brinda mucha flexibilidad en la forma en que ejecuta y administra
su instalación Airflow.
Aunque Airflow tiene muchas características ricas, varias de las opciones de diseño de Airflow pueden hacer
es menos adecuado para ciertos casos. Por ejemplo, algunos casos de uso que no son adecuados para
El flujo de aire incluye lo siguiente:
ÿ Manejo de canalizaciones de transmisión, ya que Airflow está diseñado principalmente para ejecutarse
o tareas orientadas a lotes, en lugar de cargas de trabajo de transmisión.
ÿ Implementar pipelines altamente dinámicos, en los que se agregan/eliminan tareas
entre cada corrida de tubería. Aunque Airflow puede implementar este tipo de
comportamiento dinámico, la interfaz web solo mostrará tareas que todavía están definidas en
Machine Translated by Google
la versión más reciente del DAG. Como tal, Airflow favorece las tuberías que no
no cambien de estructura cada vez que se ejecutan.
ÿ Equipos con poca o ninguna experiencia en programación (Python), como implementar
Los DAG en Python pueden ser desalentadores con poca experiencia en Python. En tales equipos,
usar un administrador de flujo de trabajo con una interfaz gráfica (como Azure Data Factory) o una
definición de flujo de trabajo estático puede tener más sentido.
ÿ Del mismo modo, el código de Python en los DAG puede volverse complejo rápidamente para un uso mayor
casos. Como tal, implementar y mantener los DAG de Airflow requiere
rigor de ingeniería para mantener las cosas mantenibles a largo plazo.
Resumen
ÿ Las canalizaciones de datos se pueden representar como DAG, que definen claramente las tareas y sus
dependencias Estos gráficos se pueden ejecutar de manera eficiente, aprovechando
cualquier paralelismo inherente a la estructura de dependencia.
Machine Translated by Google
Resumen 19
ÿ Aunque se han desarrollado muchos administradores de flujo de trabajo a lo largo de los años
para ejecutar gráficos de tareas, Airflow tiene varias características clave que lo hacen único
adecuado para implementar canalizaciones de datos eficientes y orientadas a lotes.
ÿ Airflow consta de tres componentes principales: el servidor web, el programador y
los procesos de trabajo, que trabajan juntos para programar tareas a partir de sus datos
canalizaciones y ayudarlo a monitorear sus resultados.
Machine Translated by Google
Anatomía de
un DAG de flujo de aire
En el capítulo anterior, aprendimos por qué trabajar con datos y las muchas herramientas en el
panorama de datos no es fácil. En este capítulo, comenzamos con Airflow y revisamos un flujo de
trabajo de ejemplo que utiliza componentes básicos que se encuentran en muchos flujos de trabajo.
Es útil tener algo de experiencia en Python al comenzar con Airflow, ya que los flujos de trabajo
se definen en el código de Python. La brecha en el aprendizaje de los conceptos básicos de Airflow
no es tan grande. En general, poner en marcha la estructura básica de un flujo de trabajo de Airflow
es fácil. Profundicemos en el caso de uso de un entusiasta de los cohetes para ver cómo Airflow
podría ayudarlo.
20
Machine Translated by Google
$ curl -L "https://ll.thespacedevs.com/2.0.0/launch/upcoming"
...
},
...
]}
Como puede ver, los datos están en formato JSON y brindan información sobre el lanzamiento del cohete,
y para cada lanzamiento, hay información sobre el cohete específico, como la identificación, el nombre y la
URL de la imagen. Esto es exactamente lo que John necesita, e inicialmente dibuja el plan en la figura 2.1
para recopilar las imágenes de los próximos lanzamientos de cohetes (por ejemplo, para apuntar su
protector de pantalla al directorio que contiene estas imágenes):
Sistema de
Obtener imágenes
Notificar
de cohetes
la la
John
computadora de juan computadora de juan
Basándonos en el ejemplo de la figura 2.1, podemos ver que, al final del día, el objetivo de John es tener
un directorio lleno de imágenes de cohetes, como la imagen de la figura 2.2 del cohete Ariane 5 ECA.
Notificación
Biblioteca de lanzamiento sistema
Internet
Guardar
Obtener próximos Guardar imágenes
lanzamientos de cohetes
lanzamientos Obtener imágenes de cohetes
de cohetes Notificar
la Juan
John
computadora de juan computadora
tenemos cinco flechas en el plan de Juan. Todas estas son preguntas válidas para formular mientras se
desarrolla un flujo de trabajo, pero la verdad es que no hay una respuesta correcta o incorrecta. Hay varios
puntos a tener en cuenta, sin embargo, y a lo largo de este libro trabajamos
muchos de estos casos de uso para tener una idea de lo que está bien y lo que está mal. El código para esto
el flujo de trabajo es el siguiente.
importar json
importar pathlib
en que
schedule_interval=Ninguno, correr
)
intervalo
el DAG Aplique Bash para descargar la
debería download_launches = respuesta URL con curl.
correr BashOperator( task_id="download_launches", El nombre de la tarea
bash_command="curl -o /tmp/launches.json -L
'https://ll.thespacedevs.com/2.0.0/launch/upcoming'",
dag = dag,
)
Una función de Python analizará
la respuesta y descargará todas
def _get_pictures(): # las imágenes del cohete.
Asegurarse de que existe el directorio
pathlib.Path("/tmp/images").mkdir(padres=Verdadero, exist_ok=Verdadero)
get_pictures =
PythonOperator( task_id="get_pictures", Llame a la función de Python en
python_callable=_get_pictures, dag=dag, el DAG con un PythonOperator.
notificar = BashOperator(
task_id="notificar",
bash_command='echo "Ahora hay $(ls /tmp/images/ | wc -l) imágenes."',
dag = dag,
)
Establecer el orden
Analicemos el flujo de trabajo. El DAG es el punto de partida de cualquier flujo de trabajo. Todos
las tareas dentro del flujo de trabajo hacen referencia a este objeto DAG para que Airflow sepa qué tareas
pertenecen a qué DAG.
Tenga en cuenta que el dag (en minúsculas) es el nombre asignado a la instancia del DAG (en mayúsculas)
clase. El nombre de la instancia podría tener cualquier nombre; puedes llamarlo cohete_dag o
el_nombre_que_te_guste. Haremos referencia a la variable ( dag en minúsculas) en todos los operadores, que le dice a
Airflow a qué DAG pertenece el operador.
También tenga en cuenta que establecemos schedule_interval en Ninguno. Esto significa que el DAG no se ejecutará
automáticamente. Por ahora, puede activarlo manualmente desde la interfaz de usuario de Airflow. llegaremos a
programación en el apartado 2.4.
A continuación, un script de flujo de trabajo de Airflow consta de uno o más operadores, que realizan
el trabajo real. En el listado 2.4, aplicamos BashOperator para ejecutar un comando Bash.
) Referencia a la
variable DAG
Cada operador realiza una sola unidad de trabajo, y múltiples operadores juntos forman un
flujo de trabajo o DAG en Airflow. Los operadores funcionan independientemente unos de otros, aunque
puede definir el orden de ejecución, que llamamos dependencias en Airflow. Después de todo,
Machine Translated by Google
El flujo de trabajo de John no sería útil si primero intentara descargar imágenes mientras no hay datos sobre la
ubicación de las imágenes. Para asegurarnos de que las tareas se ejecuten en el orden correcto, podemos
establecer dependencias entre tareas.
En Airflow, podemos usar el operador binario de desplazamiento a la derecha (es decir, “rshift” [>>]) para
definir dependencias entre tareas. Esto garantiza que la tarea get_pictures se ejecute solo después de que la
descarga _launches se haya completado con éxito, y la tarea de notificación se ejecute solo después de que
get_pictures se haya completado con éxito.
NOTA En Python, el operador rshift (>>) se usa para cambiar bits, que es una operación común, por
ejemplo, en bibliotecas criptográficas. En Airflow, no hay caso de uso para el cambio de bits, y el
operador rshift se anuló para proporcionar una forma legible de definir dependencias entre tareas.
Quizás se pregunte cuál es la diferencia entre tareas y operadores. Después de todo, ambos ejecutan un poco
de código. En Airflow, los operadores tienen una única responsabilidad: existen para realizar un único trabajo.
Algunos operadores realizan trabajos genéricos, como BashOperator (usado para ejecutar un script Bash) o
PythonOperator (usado para ejecutar una función de Python); otros tienen casos de uso más específicos, como
EmailOperator (usado para enviar un correo electrónico) o SimpleHTTPOperator (usado para llamar a un punto
final HTTP).
De cualquier manera, realizan una sola pieza de trabajo.
El rol de un DAG es orquestar la ejecución de una colección de operadores. Eso incluye el inicio y la
detención de los operadores, el inicio de tareas consecutivas una vez que finaliza un operador, garantizar que
se cumplan las dependencias entre los operadores, etc.
En este contexto y en toda la documentación de Airflow, vemos que los términos operador y tarea se usan
indistintamente. Desde la perspectiva del usuario, se refieren a lo mismo y, a menudo, los dos se sustituyen en
las discusiones. Los operadores proporcionan la implementación de un trabajo. Airflow tiene una clase llamada
BaseOperator y muchas subclases que heredan de BaseOperator, como PythonOperator, EmailOperator y
OracleOperator.
Sin embargo, hay una diferencia. Las tareas en Airflow gestionan la ejecución de un operador; se pueden
considerar como un pequeño envoltorio o administrador alrededor de un operador que garantiza que el
operador se ejecute correctamente. El usuario puede concentrarse en el trabajo a realizar mediante el uso de
operadores, mientras que Airflow asegura la correcta ejecución del trabajo a través de tareas (figura 2.4).
Machine Translated by Google
TROZO DE CUERO
Figura 2.4 Los usuarios de Airflow utilizan DAG y operadores. Las tareas
son componentes internos para gestionar el estado del operador y
mostrar los cambios de estado (p. ej., iniciado/finalizado) al usuario.
json.load(f)
image_urls = [lanzamiento["imagen"] para lanzamiento en lanzamientos["resultados"]]
para image_url en image_urls:
Descarga
probar:
cada imagen.
respuesta = solicitudes.get(image_url)
image_filename = image_url.split("/")[-1]
target_file = f"/tmp/images/{image_filename}"
Almacenar cada
con abierto(target_file, "wb") como f:
imagen.
f.write(respuesta.contenido)
Imprimir en salida estándar;
print(f"Descargado {image_url} a {target_file}") excepto
esto será solicitudes_excepciones.MissingSchema:
capturado en print(f"{image_url} parece ser una URL no válida.")
Registros de flujo de aire.
excepto solicitudes_excepciones.ConnectionError:
print(f"No se pudo conectar a {image_url}").
Al ejecutar el operador, se llama a la función de Python y ejecutará la función. Vamos a desglosarlo. El uso
básico de PythonOperator siempre se parece a la figura 2.5.
def _get_pictures():
# trabaja aquí... PythonOperator invocable
get_pictures = OperadorPython(
task_id="obtener_imágenes",
python_callable =_get_pictures, PythonOperador
dag=dag
)
El primer paso en el invocable es asegurarse de que el directorio en el que se almacenarán las imágenes
almacenado existe, como se muestra en el listado 2.7. A continuación, abrimos el resultado descargado de la
Inicie la API de la biblioteca y extraiga las URL de las imágenes para cada lanzamiento.
Listado 2.9 Descarga todas las imágenes de las URL de las imágenes recuperadas
para image_url en image_urls: intente: Obtén la imagen. Obtenga solo el nombre del
bucle sobre
toda la imagen archivo seleccionando todo
URL. respuesta = solicitudes.get(image_url) después del último. Por ejemplo, https://
image_filename = image_url.split("/")[-1] target_file = f"/tmp/ anfitrión/RocketImages/Electron
Construir images/{image_filename}" with open(target_file, "wb") como f: .jpg_1440.jpg ÿ Electron.jpg
el objetivo
f.write (respuesta.contenido) _1440.jpg.
ruta de archivo.
print(f"Descargado {image_url} a {target_file}") excepto Imprimir resultado.
ÿ
Pyenv: https://github.com/pyenv/pyenv
ÿ Conda: https://docs.conda.io
ÿ virtualenv: https://virtualenv.pypa.io
Después de instalar Airflow, inícielo inicializando el metastore (una base de datos en la que todos
El estado del flujo de aire se almacena), creando un usuario, copiando el lanzamiento del cohete DAG en los DAG
directorio e iniciando el programador y el servidor web:
1 inicio de base de datos de flujo de aire
2 usuarios de flujo de aire crean --nombre de usuario administrador --contraseña administrador --nombre Anónimo --apellido
3 cp download_rocket_launches.py ~/airflow/dags/
4 servidor web de flujo de aire
Tenga en cuenta que el programador y el servidor web son procesos continuos que mantienen su terminal
abierta, por lo tanto, ejecútelos en segundo plano con el servidor web airflow y/o abra un
segunda ventana de terminal para ejecutar el programador y el servidor web por separado. después de que estés
configure, vaya a http:/ /localhost:8080 e inicie sesión con el nombre de usuario "admin" y la contraseña
“admin” para ver Airflow.
NOTA Si está familiarizado con Docker, probablemente argumentará que no es deseable ejecutar
múltiples procesos en un solo contenedor de Docker como se muestra en el listado 2.10. El comando
es un solo comando, destinado a la demostración.
propósitos para ponerse en marcha rápidamente. En un entorno de producción, debe
ejecutar el servidor web, el programador y la metatienda de Airflow en contenedores separados,
explicado en detalle en el capítulo 10.
Machine Translated by Google
Descargará y ejecutará la imagen apache/airflow de Airflow Docker. Una vez que se ejecuta, puede ver
Airflow en http: //localhost:8080 e iniciar sesión con el nombre de usuario "admin" y la contraseña "admin".
La primera vista de Airflow en http:/ /localhost:8080 que verá es la pantalla de inicio de sesión, que se
muestra en la figura 2.6.
Esta vista nos muestra la estructura del script DAG proporcionado a Airflow. Una vez colocado en
el directorio de DAG, Airflow leerá el script y extraerá los fragmentos que
juntos forman un DAG, por lo que se puede visualizar en la interfaz de usuario. La vista de gráfico nos muestra la
estructura del DAG, y cómo y en qué orden se conectan todas las tareas en el DAG
y se ejecutará. Esta es una de las vistas que probablemente usará más al desarrollar sus flujos de trabajo.
La leyenda del estado muestra todos los colores que puede ver cuando se ejecuta, así que veamos qué
sucede y ejecuta el DAG. Primero, el DAG debe estar "encendido" para poder ejecutarse; palanca
el botón al lado del nombre DAG para eso. A continuación, haga clic en el botón Reproducir para ejecutarlo.
Machine Translated by Google
Después de activar el DAG, comenzará a ejecutarse y verá el estado actual del flujo de trabajo representado por
colores (figura 2.9). Dado que establecemos dependencias entre nuestras tareas, las tareas consecutivas solo
comienzan a ejecutarse una vez que se han completado las tareas anteriores. Comprobemos el resultado de la
tarea de notificación . En un caso de uso real, probablemente desee enviar un correo electrónico o, por ejemplo,
una notificación de Slack para informar sobre las nuevas imágenes. En aras de la simplicidad, ahora imprime el
número de imágenes descargadas. Revisemos los registros.
Todos los registros de tareas se recopilan en Airflow, por lo que podemos buscar en la interfaz de usuario
resultados o posibles problemas en caso de falla. Haga clic en una tarea de notificación completa y verá una
ventana emergente con varias opciones, como se muestra en la figura 2.10.
Haga clic en el botón Registro superior central para inspeccionar los registros, como se muestra en la figura
2.11. Los registros son bastante detallados de forma predeterminada, pero muestran la cantidad de imágenes
descargadas en el registro. Finalmente, podemos abrir el directorio /tmp/images y verlos. Cuando se ejecuta en
Docker, este directorio solo existe dentro del contenedor de Docker y no en su sistema host. Por lo tanto, primero
debe ingresar al contenedor Docker:
Después de eso, obtiene un terminal Bash en el contenedor y puede ver las imágenes en /tmp/images (figura
2.12).
largo2520marzo25202d_imagen_
20190222031211.jpeg
falcon2520heavy_image_
20190224025007.jpeg
largo2520marzo25203_imagen_
20200102181012.jpg
falcon25209_image_ h-iia2520202_image_
20190224025007.jpeg 20190222031201.jpeg
ariane252052520eca_image_
20190224012333.jpeg
En Airflow, podemos programar un DAG para que se ejecute en ciertos intervalos, por ejemplo, una vez por hora, día o
mes. Esto se controla en el DAG configurando el argumento intervalo_programación.
dag = dag(
dag_id="download_rocket_launches",
start_date=airflow.utils.dates.days_ago(14), schedule_interval="@daily",
Alias de flujo de aire para 0 0
)
* * * (es decir, medianoche)
Establecer el intervalo_programación en @daily le dice a Airflow que ejecute este flujo de trabajo una vez al día para que
John no tenga que activarlo manualmente una vez al día. Este comportamiento se ve mejor en la vista de árbol, como se
muestra en la figura 2.13.
La vista de árbol es similar a la vista de gráfico, pero muestra la estructura del gráfico a medida que se ejecuta a lo
largo del tiempo. En la figura 2.14 se puede ver una descripción general del estado de todas las ejecuciones de un único
flujo de trabajo.
Machine Translated by Google
La estructura del DAG se muestra para adaptarse a un diseño de "filas y columnas", específicamente el
estado de todas las ejecuciones del DAG específico, donde cada columna representa una única
ejecución en algún momento.
Cuando configuramos el intervalo de programación en @daily, Airflow sabía que tenía que ejecutar
este DAG una vez al día. Dada la fecha de inicio proporcionada al DAG de hace 14 días, eso significa
que el tiempo desde hace 14 días hasta ahora se puede dividir en 14 intervalos iguales de un día. Dado
que tanto la fecha de inicio como la de finalización de estos 14 intervalos se encuentran en el pasado,
comenzarán a ejecutarse una vez que proporcionemos un intervalo de programación a Airflow. La
semántica del intervalo de programación y varias formas de configurarlo se tratan con más detalle en el
capítulo 3.
La tarea fallida específica se mostraría en rojo tanto en el gráfico como en la vista de árbol, como resultado de no poder
obtener las imágenes de Internet y, por lo tanto, generar un error. La tarea de notificación sucesiva no se ejecutaría en absoluto
porque depende del estado exitoso de la tarea get_pictures . Estas instancias de tareas se muestran en naranja.
De forma predeterminada, todas las tareas anteriores deben ejecutarse correctamente y cualquier tarea sucesiva de una fallida
la tarea no se ejecutará.
Resolvamos el problema inspeccionando los registros nuevamente. Abra los registros de get_
tarea de imágenes (figura 2.16).
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPSConnection
objeto en 0x7f37963ce3a0>: No se pudo establecer una nueva conexión: [Errno
-2] Nombre o servicio desconocido
Esto indica que urllib3 (es decir, el cliente HTTP para Python) está intentando establecer una conexión pero no
puede, lo que podría insinuar que una regla de firewall bloquea la conexión o no.
conectividad a Internet. Suponiendo que solucionamos el problema (por ejemplo, enchufamos el cable de Internet),
reiniciemos la tarea.
NOTA No es necesario reiniciar todo el flujo de trabajo. Una buena característica del flujo de aire es
que puede reiniciar desde el punto de falla y en adelante, sin tener que reiniciar ninguna tarea exitosa
anterior.
Haga clic en la tarea fallida y luego haga clic en el botón Borrar en la ventana emergente (figura 2.17). Eso
le mostrará las tareas que está a punto de borrar, lo que significa que restablecerá el estado de estas
tareas y Airflow las volverá a ejecutar, como se muestra en la figura 2.18.
¡Haga clic en Aceptar! y se borrará la tarea fallida y sus sucesivas tareas, como se puede ver en
figura 2.19.
Resumen 39
Suponiendo que se resuelvan los problemas de conectividad, las tareas ahora se ejecutarán correctamente y la
vista de árbol completa se volverá verde (figura 2.20).
En cualquier pieza de software, hay muchas razones para fallar. En los flujos de trabajo de Airflow, a veces se
acepta la falla, a veces no y a veces solo en ciertas condiciones. Los criterios para tratar fallas se pueden
configurar en cualquier nivel del flujo de trabajo y se tratan con más detalle en el capítulo 4.
Después de borrar las tareas fallidas, Airflow volverá a ejecutar automáticamente estas tareas. Si todo va
bien, John ahora habrá descargado las imágenes del cohete resultantes de las tareas fallidas. Tenga en cuenta
que la URL llamada en la tarea download_launches simplemente solicita los próximos lanzamientos de cohetes,
lo que significa que devolverá los próximos lanzamientos de cohetes en el momento de llamar a la API. La
incorporación del contexto de tiempo de ejecución en el que se ejecutó un DAG en su código se trata en el
capítulo 4.
Resumen
ÿ Los flujos de trabajo en Airflow se representan en DAG. ÿ Los
operadores representan una única unidad de trabajo. ÿ Airflow
contiene una serie de operadores tanto para tipos genéricos como específicos de
trabajar.
ÿ La interfaz de usuario de Airflow ofrece una vista de gráfico para ver la estructura DAG y la vista de árbol
para ver carreras DAG a lo largo del
tiempo. ÿ Las tareas fallidas se pueden reiniciar en cualquier parte del DAG.
Machine Translated by Google
Programación en Airflow
En el capítulo anterior, exploramos la interfaz de usuario de Airflow y le mostramos cómo definir un DAG
de Airflow básico y ejecutarlo todos los días mediante la definición de un intervalo programado. En este
capítulo, profundizaremos un poco más en el concepto de programación en Airflow y exploraremos cómo
esto le permite procesar datos de forma incremental a intervalos regulares. Primero, presentaremos un
pequeño caso de uso centrado en el análisis de eventos de usuarios de nuestro sitio web y exploraremos
cómo podemos crear un DAG para analizar estos eventos a intervalos regulares.
A continuación, exploraremos formas de hacer que este proceso sea más eficiente adoptando un enfoque
incremental para analizar nuestros datos y comprender cómo se relaciona esto con el concepto de fechas
de ejecución de Airflow. Finalmente, terminaremos mostrando cómo podemos llenar los vacíos anteriores
en nuestro conjunto de datos mediante el relleno y discutiendo algunas propiedades importantes de las
tareas de Airflow adecuadas.
40
Machine Translated by Google
Por razones prácticas, el servicio de seguimiento externo no almacena datos durante más de 30 días, por lo que debemos
almacenar y acumular estos datos nosotros mismos, ya que queremos conservar nuestro historial durante períodos de tiempo
más prolongados. Normalmente, debido a que los datos sin procesar pueden ser bastante grandes, tendría sentido almacenar
estos datos en un servicio de almacenamiento en la nube como S3 de Amazon o Cloud Storage de Google, ya que combinan
una alta durabilidad con costos relativamente bajos. Sin embargo, en aras de la simplicidad, no nos preocuparemos por estas
cosas y mantendremos nuestros datos localmente.
Para simular este ejemplo, hemos creado una API simple (local) que nos permite recuperar eventos de usuario. Por
ejemplo, podemos recuperar la lista completa de eventos disponibles de los últimos 30 días mediante la siguiente llamada a
la API:
Esta llamada devuelve una lista (codificada en JSON) de eventos de usuario que podemos analizar para calcular nuestras
estadísticas de usuario.
Usando esta API, podemos dividir nuestro flujo de trabajo en dos tareas separadas: una para obtener eventos de usuario
y otra para calcular las estadísticas. Los datos en sí se pueden descargar usando BashOperator, como vimos en el capítulo
anterior. Para calcular las estadísticas, podemos usar PythonOperator, que nos permite cargar los datos en un Pandas
DataFrame y calcular la cantidad de eventos usando un grupo y una agregación.
Listado 3.1 Versión inicial (no programada) del evento DAG (dags/01_unscheduled.py)
dag = dag(
Defina la fecha de
dag_id="01_no programado",
inicio para el DAG.
start_date=dt.datetime(2019, 1, 1),
schedule_interval=Ninguno,
Especifique que se trata
) de un DAG no programado.
Machine Translated by Google
fetch_events = BashOperator(
task_id="obtener_eventos",
bash_command=(
"
"mkdir -p /datos && "curl
Obtenga y almacene los
-o /datos/eventos.json "
eventos de la API.
"https:/ /localhost:5000/eventos"
),
dag=dag,
)
Ahora tenemos nuestro DAG básico, pero aún debemos asegurarnos de que se ejecute regularmente mediante el
flujo de aire. ¡Vamos a programarlo para que tengamos actualizaciones diarias!
En nuestro ejemplo de ingesta de eventos de usuario, nos gustaría calcular estadísticas diariamente, por lo que
tendría sentido programar nuestro DAG para que se ejecute una vez al día. Como esto es común
caso de uso, Airflow proporciona la macro conveniente @daily para definir una programación diaria
intervalo, que ejecuta nuestro DAG una vez al día a la medianoche.
Machine Translated by Google
Airflow también necesita saber cuándo queremos comenzar a ejecutar el DAG, especificado por su
fecha de inicio. Con base en esta fecha de inicio, Airflow programará la primera ejecución de nuestro
DAG para ejecutarse en el primer intervalo de programación después de la fecha de inicio (inicio + intervalo). Las
ejecuciones subsiguientes continuarán ejecutándose en intervalos de programación después de este primer intervalo.
NOTA Preste atención al hecho de que Airflow inicia las tareas en un intervalo en el
final del intervalo. Si desarrolla un DAG el 1 de enero de 2019 a las 13:00, con un
start_date de 01-01-2019 e @intervalo diario , esto significa que comienza a ejecutarse por primera vez a
la medianoche. Al principio, no pasará nada si ejecuta el DAG en enero
1 a las 13:00 hasta llegar a la medianoche.
Por ejemplo, supongamos que definimos nuestro DAG con una fecha de inicio el primero de enero, como se mostró
anteriormente en el listado 3.2. Combinado con un intervalo de programación diario, esto resultará en
Airflow ejecutando nuestro DAG a la medianoche todos los días posteriores al primero de enero (figura 3.1). Tenga en
cuenta que nuestra primera ejecución tiene lugar el dos de enero (el primer
intervalo siguiente a la fecha de inicio) y no el primero. Entraremos en el razonamiento detrás
este comportamiento más adelante en este capítulo (sección 3.4).
comienzo Futuro
fecha ejecuciones
2019-01-01 2019-01-02 2019-01-03 2019-01-04
00:00 00:00 00:00 00:00
Figura 3.1 Intervalos de programación para un DAG programado diario con una fecha de
inicio especificada (2019-01-01). Las flechas indican el punto de tiempo en el que se ejecuta un DAG.
Sin una fecha de finalización especificada, el DAG seguirá ejecutándose todos los
días hasta que se apague.
Sin una fecha de finalización, Airflow (en principio) seguirá ejecutando nuestro DAG en este día.
calendario hasta el final de los tiempos. Sin embargo, si ya sabemos que nuestro proyecto tiene un
duración fija, podemos decirle a Airflow que deje de ejecutar nuestro DAG después de una fecha determinada usando
el parámetro end_date .
Machine Translated by Google
dag = dag(
dag_id="03_con_fecha_de_finalización",
intervalo_de_horario="@diario",
start_date=dt.datetime(año=2019, mes=1, día=1),
end_date=dt.datetime(año=2019, mes=1, día=5),
)
Esto dará como resultado el conjunto completo de intervalos de programación que se muestra en la figura 3.2.
comienzo Final
fecha fecha
Figura 3.2 Programar intervalos para un DAG programado diariamente con fechas de inicio
(2019-01-01) y finalización (2019-01-05) especificadas, lo que evita que el DAG se ejecute más allá de esta fecha
#*****
En esta definición, un trabajo cron se ejecuta cuando los campos de especificación de hora/fecha
coincida con la hora/fecha actual del sistema. Se pueden utilizar asteriscos (*) en lugar de números para
definir campos sin restricciones, lo que significa que no nos importa el valor de ese campo.
Aunque esta representación basada en cron puede parecer un poco complicada, nos proporciona
con una gran flexibilidad para definir intervalos de tiempo. Por ejemplo, podemos definir
intervalos por hora, diarios y semanales utilizando las siguientes expresiones cron:
Machine Translated by Google
Además de esto, también podemos definir expresiones más complicadas como las siguientes:
Además, las expresiones cron le permiten definir colecciones de valores usando una coma
(,) para definir una lista de valores o un guión (-) para definir un rango de valores. Usando esta sintaxis,
podemos crear expresiones que permitan ejecutar trabajos en varios días de la semana o varios
conjuntos de horas durante un día:
Airflow también brinda soporte para varias macros que representan la forma abreviada de los intervalos de programación
de uso común. Ya hemos visto una de estas macros (@daily)
para definir los intervalos diarios. Una descripción general de las otras macros admitidas por Airflow es
se muestra en la tabla 3.1.
Tabla 3.1 Valores predeterminados de flujo de aire para intervalos de programación utilizados con frecuencia
Preestablecido Sentido
@semanalmente Corre una vez por semana a la medianoche del domingo por la mañana.
@monthly Ejecutar una vez al mes a la medianoche del primer día del mes.
Aunque las expresiones de Cron son extremadamente poderosas, puede ser difícil trabajar con ellas.
Como tal, puede ser una buena idea probar su expresión antes de probarla en Airflow.
Afortunadamente, existen muchas herramientas1 disponibles en línea que pueden ayudarlo a definir, verificar o
explique sus expresiones Cron en inglés sencillo. Tampoco está de más documentar el
razonamiento detrás de complicadas expresiones cron en su código. Esto puede ayudar a otros
(¡incluido el futuro usted!) entienda la expresión cuando revise su código.
1
https://crontab.guru traduce las expresiones cron a un lenguaje legible por humanos.
Machine Translated by Google
Esta limitación de cron se deriva de la naturaleza de las expresiones cron, ya que definen un patrón que
se compara continuamente con la hora actual para determinar si se debe ejecutar un trabajo. Esto tiene la
ventaja de hacer que las expresiones no tengan estado, lo que significa que no tiene que recordar cuándo
se ejecutó un trabajo anterior para calcular el siguiente intervalo. Sin embargo, como puede ver, esto tiene
el precio de cierta expresividad.
¿Qué pasa si realmente queremos ejecutar nuestro DAG una vez cada tres días? Para admitir este tipo
de programación basada en la frecuencia, Airflow también le permite definir intervalos de programación en
términos de un intervalo de tiempo relativo. Para usar una programación basada en la frecuencia, puede
pasar una instancia de timedelta (desde el módulo de fecha y hora en la biblioteca estándar) como un
intervalo de programación.
Esto daría como resultado que nuestro DAG se ejecute cada tres días después de la fecha de inicio (los días
4, 7, 10 y así sucesivamente de enero de 2019). Por supuesto, también puede usar este enfoque para
ejecutar su DAG cada 10 minutos (usando timedelta (minutos = 10)) o cada dos horas (usando timedelta
(horas = 2)).
Eventos
Buscar Agregar
Día 1 eventos/día1.json estadísticas/día1.csv
Buscar Agregar
Dia 2 eventos/día2.json estadísticas/día2.csv
Día 3
Juntos, estos parámetros de fecha indican el intervalo de tiempo para el que nos gustaría
obtener eventos. Tenga en cuenta que en este ejemplo start_date es inclusivo, mientras que end_date es
exclusivo, lo que significa que estamos recuperando eventos que ocurren entre 2019-01-01
00:00:00 y 2019-01-01 23:59:59.
Podemos implementar esta obtención de datos incremental en nuestro DAG cambiando nuestro
comando bash para incluir las dos fechas.
fetch_events = BashOperator(
task_id="obtener_eventos",
bash_command=(
"
"mkdir -p /data && "curl
-o /data/events.json " "http:/ /
localhost:5000/events?"
"start_date=2019-01-01&"
"fecha_finalización=2019-01-02"
Machine Translated by Google
),
dag=dag,
)
Sin embargo, para obtener datos para cualquier otra fecha que no sea 2019-01-01, debemos cambiar el
comando para usar fechas de inicio y finalización que reflejen el día en que se ejecuta el DAG.
Afortunadamente, Airflow nos brinda varios parámetros adicionales para hacerlo, que exploraremos en la
siguiente sección.
Para muchos flujos de trabajo que implican procesos basados en el tiempo, es importante saber en qué
intervalo de tiempo se ejecuta una tarea determinada. Por esta razón, Airflow proporciona tareas con
parámetros adicionales que se pueden usar para determinar en qué intervalo de programación se ejecuta
una tarea (entraremos en más detalles sobre estos parámetros en el próximo capítulo).
El más importante de estos parámetros es la fecha_ejecución, que representa la fecha y la hora en
que se ejecuta nuestro DAG. Al contrario de lo que sugiere el nombre del parámetro, la fecha_ejecución no
es una fecha sino una marca de tiempo, que refleja la hora de inicio del intervalo de programación para el
que se ejecuta el DAG. La hora de finalización del intervalo de programación se indica mediante otro
parámetro denominado next_execution_date. Juntas, estas fechas definen la duración total del intervalo de
programación de una tarea (figura 3.4).
Fecha de Fecha de
ejecución anterior ejecución Próxima fecha de ejecución
Intervalo
actual
Fecha Futuras
de inicio ejecuciones
Ahora
Airflow también proporciona un parámetro anterior_execution_date , que describe el inicio del intervalo de
programación anterior. Aunque no usaremos este parámetro aquí, puede ser útil para realizar análisis que
contrasten los datos del intervalo de tiempo actual con los resultados del intervalo anterior.
En Airflow, podemos usar estas fechas de ejecución al hacer referencia a ellas en nuestros operadores.
Por ejemplo, en BashOperator, podemos usar la funcionalidad de plantillas de Airflow para incluir las fechas
de ejecución de forma dinámica en nuestro comando Bash. Las plantillas se tratan en detalle en el capítulo
4.
Machine Translated by Google
fetch_events = BashOperator(
formateado
task_id="obtener_eventos",
fecha de ejecución
bash_command=(
" insertado con
"mkdir -p /datos && "curl -o /
Plantillas Jinja
datos/eventos.json"
"http:/ /localhost:5000/eventos?"
"start_date={{execution_date.strftime('%Y-%m-%d')}}"
"&end_date={{next_execution_date.strftime('%Y-%m-%d')}}"
),
dag = dag, next_execution_date contiene el
) fecha de ejecución del siguiente intervalo.
En este ejemplo, la sintaxis {{variable_name}} es un ejemplo del uso de Jinja de Airflow basado (http://
jinja.pocoo.org) sintaxis de plantillas para hacer referencia a uno de los parámetros específicos de Airflow. Aquí,
usamos esta sintaxis para hacer referencia a las fechas de ejecución y el formato.
en el formato de cadena esperado utilizando el método datetime strftime (ya que ambas fechas de ejecución son
objetos datetime).
Debido a que los parámetros de fecha_ejecución a menudo se usan de esta manera para hacer referencia a
fechas como cadenas formateadas, Airflow también proporciona varios parámetros abreviados
para formatos de fecha comunes. Por ejemplo, los parámetros ds y ds_nodash son
representaciones diferentes de la fecha_ejecución , formateadas como AAAA-MM-DD y
AAAA MDD, respectivamente. Del mismo modo, next_ds, next_ds_nodash, prev_ds y prev_ds_nodash
proporcionar notaciones abreviadas para las fechas de ejecución siguiente y anterior, respectivamente.2
Usando estas notaciones abreviadas, también podemos escribir nuestro comando de búsqueda incremental
de la siguiente manera.
fetch_events = BashOperator(
task_id="obtener_eventos",
bash_command=(
"
"mkdir -p /datos && "curl -o /
datos/eventos.json" ds proporciona la
fecha_de_ejecución
"http:/ /localhost:5000/eventos?"
con formato AAAA MM-DD.
"start_date={{ds}}&"
"end_date={{next_ds}}"
next_ds proporciona
),
lo mismo para next_
dag = dag, fecha de ejecución.
)
Esta versión más corta es un poco más fácil de leer. Sin embargo, para fechas más complicadas (o
datetime), es probable que aún necesite usar el método strftime más flexible.
2
Consulte https://airflow.readthedocs.io/en/stable/macros-ref.html para obtener una descripción general de todas las abreviaturas disponibles
opciones
Machine Translated by Google
Una forma de resolver este problema es simplemente agregar nuevos eventos a events.json
archivo, lo que nos permitiría construir nuestro historial en un solo archivo JSON. Sin embargo, una desventaja de este
enfoque es que requiere cualquier trabajo de procesamiento posterior para cargar el
conjunto completo de datos, incluso si solo estamos interesados en calcular estadísticas para un día determinado.
Además, también hace que este archivo sea un único punto de falla, por lo que podemos correr el riesgo de perder
todo nuestro conjunto de datos en caso de que este archivo se pierda o se corrompa.
Un enfoque alternativo es dividir nuestro conjunto de datos en lotes diarios escribiendo el
salida de la tarea a un archivo que lleva el nombre de la fecha de ejecución correspondiente.
Listado 3.8 Escritura de datos de eventos en archivos separados por fecha (dags/08_templated_path.py)
fetch_events = BashOperator(
task_id="obtener_eventos",
bash_command=(
" Respuesta escrita en
"mkdir -p /data/events && "curl -o /data/
nombre de archivo con plantilla
events/{{ds}}.json " "http:/ /localhost:5000/events?"
"start_date={{ds}}&"
"end_date={{next_ds}}", dag=dag,
Esto daría como resultado que se descarguen datos para una fecha de ejecución de 2019-01-01
siendo escrito en el archivo /data/events/2019-01-01.json.
Esta práctica de dividir un conjunto de datos en partes más pequeñas y más manejables es una estrategia común
en los sistemas de almacenamiento y procesamiento de datos y se conoce comúnmente como
partición, con las piezas más pequeñas de un conjunto de datos las particiones. La ventaja de particionar nuestro
conjunto de datos por fecha de ejecución se hace evidente cuando consideramos la segunda
tarea en nuestro DAG (calculate_stats), en el que calculamos estadísticas para cada día
valor de los eventos de usuario. En nuestra implementación anterior, estábamos cargando todos los datos
establecer y calcular estadísticas para todo nuestro historial de eventos, todos los días.
calcular_estadísticas = OperadorPython(
task_id="calcular_estadísticas",
python_callable=_calculate_stats,
op_kwargs={
"ruta_de_entrada": "/datos/eventos.json",
"output_path": "/datos/estadísticas.csv",
},
dag = dag,
)
Sin embargo, al usar nuestro conjunto de datos particionados, podemos calcular estas estadísticas de
manera más eficiente para cada partición separada al cambiar las rutas de entrada y salida de esta tarea.
para señalar los datos de eventos particionados y un archivo de salida particionado.
calcular_estadísticas = OperadorPython(
task_id="calcular_estadísticas",
python_callable=_calculate_stats,
Pasar los valores que nosotros
templates_dict={
quiere ser plantilla.
"ruta_de_entrada": "/datos/eventos/{{ds}}.json",
"ruta_de_salida": "/datos/estadísticas/{{ds}}.csv",
},
dag = dag,
)
Aunque estos cambios pueden parecer algo complicados, en su mayoría involucran código de placa de
caldera para garantizar que nuestras rutas de entrada y salida tengan plantillas. Lograr esto
plantilla en PythonOperator, necesitamos pasar cualquier argumento que deba ser una plantilla usando el
parámetro templates_dict del operador. Entonces podemos recuperar el
valores con plantilla dentro de nuestra función desde el objeto de contexto que se pasa a nuestro
Función _calculate_stats de Airflow.3
Si todo esto fue demasiado rápido, no se preocupe; nos sumergiremos en el contexto de la tarea en
más detalle en el siguiente capítulo. El punto importante a entender aquí es que estos
3
Para Airflow 1.10.x, deberá pasar el argumento adicional provide_context=True a PythonOperator;
de lo contrario, la función _calculate_stats no recibirá los valores de contexto.
Machine Translated by Google
Los cambios nos permiten calcular nuestras estadísticas de forma incremental, procesando solo un pequeño
subconjunto de nuestros datos cada día.
fechas de ejecución son una parte tan importante de Airflow, tomemos un minuto para asegurarnos de que
entendemos completamente cómo se definen estas fechas.
En esta representación de tiempo basada en intervalos, se ejecuta un DAG para un intervalo dado tan pronto
como ha pasado el intervalo de tiempo de ese intervalo. Por ejemplo, el primer intervalo de la figura 3.5 se
ejecutaría lo antes posible después de 2019-01-01 23:59:59, porque para entonces ya ha pasado el último punto
del intervalo. De manera similar, el DAG se ejecutaría para el segundo intervalo poco después del 2019-01-02
23:59:59, y así sucesivamente, hasta llegar a nuestra fecha de finalización opcional.
Una ventaja de usar este enfoque basado en intervalos es que es ideal para realizar el tipo de procesamiento
de datos incremental que vimos en las secciones anteriores, ya que sabemos exactamente durante qué intervalo
de tiempo se ejecuta una tarea: el inicio y el final de la tarea. intervalo de respuesta correspondiente. Esto está
en marcado contraste con, por ejemplo, un sistema de programación basado en puntos de tiempo como cron,
donde solo sabemos la hora actual en la que se ejecuta nuestra tarea. Esto significa que, por ejemplo en cron,
tenemos que calcular o adivinar dónde quedó nuestra ejecución anterior suponiendo que la tarea se está
ejecutando el día anterior (figura 3.6).
Comprender que el manejo del tiempo de Airflow se basa en intervalos de programación también ayuda a
comprender cómo se definen las fechas de ejecución dentro de Airflow. Por ejemplo, supongamos que tenemos
un DAG que sigue un intervalo de programación diario y luego consideramos el intervalo correspondiente que
debe procesar los datos para 2019-01-03. En Airflow, este intervalo se ejecutará poco después de 2019-01-04
00:00:00, porque en ese momento sabemos que ya no lo haremos.
Machine Translated by Google
Ahora
Corre por
esto explícito
intervalo
basado en intervalos
Planificación
Adivina dónde
intervalo
empieza/termina
nuestro DAG se ejecuta realmente. Desafortunadamente, el nombre puede ser un poco confuso.
Con las fechas de ejecución de Airflow definidas como el inicio del correspondiente
intervalos de programación, se pueden utilizar para derivar el inicio y el final de un intervalo específico
(figura 3.7). Por ejemplo, al ejecutar una tarea, el inicio y el final del intervalo correspondiente están definidos
por la fecha_ejecución (el inicio del intervalo) y el
next_execution date (el inicio del siguiente intervalo) parámetros. De manera similar, el intervalo de
programación anterior se puede derivar usando la fecha_ejecución_anterior y
parámetros de fecha_ejecución .
Sin embargo, una advertencia a tener en cuenta al usar la fecha de ejecución anterior
y next_execution_date en sus tareas es que estos solo están definidos para
Machine Translated by Google
fecha
2019-01-01 2019-01-02 2019-01-03 2019-01-04
00:00 00:00 00:00 00:00
DAG se ejecuta siguiendo el intervalo de programación. Como tal, los valores de estos parámetros
ser indefinido para cualquier ejecución que se active manualmente usando Airflow UI o CLI porque
Airflow no puede proporcionar información sobre los intervalos de programación anteriores o siguientes si
no están siguiendo un intervalo de programación.
dag = dag(
dag_id="09_no_ponerse al día",
intervalo_de_horario="@diario",
start_date=dt.datetime(año=2019, mes=1, día=1),
end_date=dt.datetime(año=2019, mes=1, día=5),
ponerse al día = falso,
)
Con esta configuración, el DAG solo se ejecutará para el intervalo de programación más reciente en lugar de
que ejecutar todos los intervalos pasados abiertos (figura 3.8). El valor predeterminado para ponerse al día puede
Machine Translated by Google
Fecha Ahora
Intervalo
de inicio
actual
controlarse desde el archivo de configuración de Airflow estableciendo un valor para la opción de configuración
catch up_by_default .
Aunque el reabastecimiento es un concepto poderoso, está limitado por la disponibilidad de datos en los sistemas
de origen. Por ejemplo, en nuestro caso de uso de ejemplo, podemos cargar eventos pasados desde nuestra API
especificando una fecha de inicio de hasta 30 días en el pasado. Sin embargo, dado que la API solo proporciona
hasta 30 días de historial, no podemos usar el relleno para cargar datos de días anteriores.
La reposición también se puede usar para reprocesar datos después de que hayamos realizado cambios en
nuestro código. Por ejemplo, digamos que hacemos un cambio en nuestra función calc_statistics para agregar una
nueva estadística. Al usar el relleno, podemos borrar ejecuciones anteriores de nuestra tarea calc_statistics para
volver a analizar nuestros datos históricos usando el nuevo código. Tenga en cuenta que en este caso no estamos
limitados por el límite de 30 días de nuestra fuente de datos, ya que ya hemos cargado estas particiones de datos
anteriores como parte de nuestras ejecuciones anteriores.
3.6.1 Atomicidad
El término atomicidad se usa con frecuencia en los sistemas de bases de datos, donde una transacción atómica se
considera una serie indivisible e irreducible de operaciones de bases de datos de modo que ocurren todas o no
ocurre nada. De manera similar, en Airflow, las tareas deben definirse de modo que
Machine Translated by Google
o tienen éxito y producen algún resultado adecuado o fallan de una manera que no afecta el estado del
sistema (figura 3.9).
Línea Línea
1 Línea 1 Línea
2 Línea 2 Línea
3 . . . fallar . . . 3 . . . fallar . . .
Figura 3.9 La atomicidad asegura que todo o nada se complete. No se produce la mitad del trabajo y, como
resultado, se evitan resultados incorrectos en el futuro.
Como ejemplo, considere una extensión simple para nuestro evento de usuario DAG, en el que nos gustaría
agregar alguna funcionalidad que envíe un correo electrónico de nuestros 10 usuarios principales al final de
cada ejecución. Una forma simple de agregar esto es extender nuestra función anterior con una llamada
adicional a alguna función que envíe un correo electrónico que contenga nuestras estadísticas.
Listado 3.12 Dos trabajos en una tarea, para romper la atomicidad (dags/10_non_atomic_send.py)
def _calculate_stats(**contexto):
"""Calcula estadísticas de eventos."""
ruta_entrada = contexto["templates_dict"]["ruta_entrada"] ruta_salida =
contexto["templates_dict"]["ruta_salida"]
email_stats(estadísticas, email="usuario@ejemplo.com")
Desafortunadamente, un inconveniente de este enfoque es que la tarea ya no es atómica. ¿Puedes ver por
qué? Si no, considere lo que sucede si nuestra función _send_stats falla (lo que seguramente sucederá si
nuestro servidor de correo electrónico es un poco inestable). En este caso, ya habremos escrito nuestras
estadísticas en el archivo de salida en output_path, haciendo que parezca que nuestra tarea tuvo éxito
aunque terminó en un error.
Para implementar esta funcionalidad de manera atómica, podríamos simplemente dividir el
funcionalidad de correo electrónico en una tarea separada.
Machine Translated by Google
De esta manera, el hecho de no enviar un correo electrónico ya no afecta el resultado de las estadísticas de cálculo .
task, pero solo falla send_stats, lo que hace que ambas tareas sean atómicas.
A partir de este ejemplo, podría pensar que separar todas las operaciones en operaciones individuales
tareas es suficiente para que todas nuestras tareas sean atómicas. Sin embargo, esto no es necesariamente verdad. A
comprenda por qué, piense si nuestra API de eventos nos hubiera requerido iniciar sesión antes de consultar eventos.
Por lo general, esto requeriría una llamada API adicional para obtener algún token de autenticación, después de lo
cual podemos comenzar a recuperar nuestros eventos.
Siguiendo nuestro razonamiento anterior de una operación = una tarea, tendríamos que
dividir estas operaciones en dos tareas separadas. Sin embargo, hacerlo crearía una fuerte
dependencia entre ellos, ya que la segunda tarea (obtener los eventos) fallará sin
ejecutando el primero poco antes. Esta fuerte dependencia entre los medios que probablemente
es mejor mantener ambas operaciones dentro de una sola tarea, permitiendo que la tarea forme una unidad de trabajo
única y coherente.
La mayoría de los operadores Airflow ya están diseñados para ser atómicos, por lo que muchos
los operadores incluyen opciones para realizar operaciones estrechamente acopladas, como la autenticación interna.
Sin embargo, los operadores más flexibles, como Python y Bash, pueden requerir que piense detenidamente en sus
operaciones para asegurarse de que sus tareas
permanecer atómico.
3.6.2 Idempotencia
Otra propiedad importante a tener en cuenta al escribir tareas de Airflow es la idempotencia.
Se dice que las tareas son idempotentes si se llama a la misma tarea varias veces con el mismo
entradas no tiene ningún efecto adicional. Esto significa que volver a ejecutar una tarea sin cambiar
las entradas no deben cambiar la salida general.
Por ejemplo, considere nuestra última implementación de la tarea fetch_events , que
obtiene los resultados de un solo día y los escribe en nuestro conjunto de datos particionado.
Machine Translated by Google
fetch_events =
BashOperator( task_id="fetch_events",
bash_command=( "mkdir -p /data/
"
events && "curl -o /data/events/
{{ds}}.json " "http:/ /localhost:5000/events? "
Particionamiento configurando
"start_date={{ds}}&" "end_date={{next_ds}}"
un nombre de archivo con plantilla
),
dag=dag,
)
Volver a ejecutar esta tarea para una fecha determinada daría como resultado que la tarea obtenga el mismo
conjunto de eventos que su ejecución anterior (suponiendo que la fecha esté dentro de nuestra ventana de 30
días) y sobrescriba el archivo JSON existente en la carpeta /data/events, produciendo el mismo resultado
Como tal, esta implementación de la tarea de obtención de eventos es claramente idempotente.
Para mostrar un ejemplo de una tarea no idempotente, considere usar un solo archivo JSON (/data/
events.json) y simplemente agregue eventos a este archivo. En este caso, volver a ejecutar una tarea daría
como resultado que los eventos simplemente se agregaran al conjunto de datos existente, duplicando así los
eventos del día (figura 3.10). Como tal, esta implementación no es indiferente, ya que las ejecuciones
adicionales de la tarea cambian el resultado general.
Figura 3.10 Una tarea idempotente produce el mismo resultado, sin importar cuántas veces la ejecute.
La idempotencia asegura la consistencia y la capacidad de lidiar con el fracaso.
En general, las tareas que escriben datos pueden volverse idempotentes comprobando los resultados
existentes o asegurándose de que la tarea sobrescriba los resultados anteriores. En conjuntos de datos
particionados en el tiempo, esto es relativamente sencillo, ya que simplemente podemos sobrescribir la
partición correspondiente. De manera similar, para los sistemas de bases de datos, podemos usar operaciones
upsert para insertar datos, lo que nos permite sobrescribir filas existentes que fueron escritas por ejecuciones de tareas anteriores.
Machine Translated by Google
Resumen 59
Sin embargo, en aplicaciones más generales, debe considerar cuidadosamente todos los efectos
secundarios de su tarea y asegurarse de que se realicen de manera idempotente.
Resumen
ÿ Los DAG pueden ejecutarse a intervalos regulares configurando el intervalo
de programación. ÿ El trabajo de un intervalo se inicia al final del intervalo.
ÿ El intervalo de programación se puede configurar con expresiones cron y timedelta. ÿ Los
datos pueden procesarse incrementalmente configurando dinámicamente variables con
plantillas
ÿ La fecha de ejecución se refiere a la fecha y hora de inicio del intervalo, no a la hora real de
ejecución.
ÿ Un DAG puede retroceder en el tiempo con el relleno. ÿ La
idempotencia garantiza que las tareas se puedan volver a ejecutar mientras se producen los mismos resultados de salida.
Machine Translated by Google
Plantillas de tareas
usando el contexto de Airflow
En los capítulos anteriores, tocamos la superficie de cómo los DAG y los operadores trabajan
juntos y cómo programar un flujo de trabajo en Airflow. En este capítulo, analizamos en
profundidad qué representan los operadores, qué son, cómo funcionan y cuándo y cómo se
ejecutan. También demostramos cómo se pueden usar los operadores para comunicarse con
sistemas remotos a través de ganchos, lo que le permite realizar tareas como cargar datos en
una base de datos, ejecutar un comando en un entorno remoto y realizar cargas de trabajo
fuera de Airflow.
60
Machine Translated by Google
Siempre que trabaje con cualquier tipo de datos, estos son detalles esenciales. Cualquier dato,
tanto pequeño como grande, puede ser complejo y es importante contar con un plan técnico de enfoque
antes de construir una canalización. La solución siempre depende de lo que usted u otros usuarios
quieran hacer con los datos, así que hágase a sí mismo y a otros preguntas como "¿Queremos volver
a procesar los datos en algún otro momento en el futuro?"; “¿Cómo recibo los datos (p. ej., frecuencia,
tamaño, formato, tipo de fuente)?”; y “¿Qué vamos a construir con los datos?” Después de conocer las
respuestas a tales preguntas, podemos abordar los detalles técnicos.
Descarguemos un solo volcado por hora e inspeccionemos los datos a mano. Para desarrollar un
pipeline de datos, debemos entender cómo cargarlo de forma incremental y cómo trabajar los datos
(figura 4.1).
1
https://dumps.wikimedia.org/other/pageviews. La estructura y los detalles técnicos de los datos de páginas vistas
de Wikipedia se documentan aquí: https://meta.wikimedia.org/wiki/Research:Page_view y https://
wikitech.wikimedia.org/wiki/Analytics/Data_Lake/Traffic/Pageviews .
Machine Translated by Google
aa Main_Page 1 0 aa
Special:GlobalUsers/sysadmin 1 0 aa User_talk:Qoan
1 0 aa Wikipedia:Community_Portal 1 0 aa.d
Main_Page 2 0 aa.m Main_Page 1 0 ab 1005 1 0
ab 1150 1 0
El contenido del archivo proporciona
los siguientes elementos, separados
por espacios en blanco: 1. Código
de dominio 2. Título de la página 3.
Número de vistas 4. Tamaño de la
respuesta en bytes Entonces, por
Vemos que las URL siguen un patrón fijo, que podemos usar al descargar los datos por
lotes (mencionado brevemente en el capítulo 3). Como experimento mental y para validar
los datos, veamos cuáles son los códigos de dominio más utilizados para el 7 de julio, de
10:00 a 11:00 (figura 4.2).
Ver los mejores resultados, 1061202 en y 995600 en.m, nos dice que los dominios
más vistos entre las 10:00 y las 11:00 del 7 de julio son "en" y "en.m" (la versión móvil
de .en), lo que hace sentido dado Inglés es el idioma más utilizado en el mundo. Además,
los resultados se devuelven tal como esperamos verlos, lo que confirma que no hay
caracteres inesperados ni desalineación de columnas, lo que significa que no tenemos
que realizar ningún procesamiento adicional para limpiar los datos. A menudo, limpiar y
transformar los datos en un estado consistente es una gran parte del trabajo.
Machine Translated by Google
1061202 en
995600 en.m Ejemplo:
aa Main_Page 3 0 af
300753 ja.m
286381 de.m Ford_EcoSport 0 1 ab 9 1
11 1 0 ab 2009 0 1
257751 de
226334 ru 201930
ja 198182 fr.m Automóvil club británico
193331 ru.m ab
171510 it.m ab ab
ab
ab
af
1 aa
2 ab
1 af
2 ab
1 af
1 aa
Figura 4.2 Primer análisis simple de los datos de páginas vistas de Wikimedia
Wikipedia
páginas Almacenamiento local Páginas vistas
vistas de Wikipedia durante una hora Datos requeridos
para una hora
El primer paso es descargar el archivo .zip para cada intervalo. La URL se construye con
varios componentes de fecha y hora:
https://dumps.wikimedia.org/other/pageviews/ {año}/{año}-{mes}/
pageviews-{año}{mes}{día}-{hora}0000.gz
Machine Translated by Google
Para cada intervalo, tendremos que insertar la fecha y la hora de ese intervalo específico en la
URL. En el capítulo 3, abordamos brevemente la programación y cómo usar la fecha de ejecución
en nuestro código para ejecutar un intervalo específico. Profundicemos un poco más en cómo
funciona. Hay muchas formas de descargar las páginas vistas; sin embargo, centrémonos en
BashOperator y PythonOperator. El método para insertar variables en tiempo de ejecución en esos
operadores se puede generalizar a todos los demás tipos de operadores.
dag =
DAG( dag_id="chapter4_stocksense_bashoperator",
start_date=airflow.utils.dates.days_ago(3),
schedule_interval="@hourly",
)
get_data =
BashOperator( task_id="get_data",
bash_command=( "curl -o /tmp/
wikipageviews.gz " "https://dumps.wikimedia.org/ Las llaves dobles
indican una variable
other/pageviews/" "{{ejecución_fecha.año }}/"
insertada en tiempo de ejecución.
"{{ fecha_ejecución.año }}-" "{{ '{:02}'.formato(fecha_ejecución.mes) }}/"
"páginas vistas-{{ fecha_ejecución.año }}"
"{{ '{:02}' .format(fecha_ejecución.mes) }}"
"{{ '{:02}'.format(fecha_ejecución.día) }}-"
"{{ '{:02}'.format(fecha_ejecución.hora) }}0000. gz"), dag=dag, Se puede proporcionar
cualquier variable o
expresión de Python.
El valor del nombre no se conoce durante la programación porque el usuario ingresará su nombre en el
formulario en tiempo de ejecución. Lo que sí sabemos es que el valor insertado se asigna a una variable
llamada nombre, y luego podemos proporcionar una cadena con plantilla, "¡Hola {{ nombre }}!", para
representar e insertar el valor de nombre en tiempo de ejecución.
En Airflow, tiene una serie de variables disponibles en tiempo de ejecución desde el contexto de la
tarea. Una de estas variables es la fecha_ejecución. Airflow utiliza el Péndulo (https:// pendulum.eustace.io)
biblioteca para fechas y horas, y la fecha_ejecución es un objeto de fecha y hora de Pendulum. Es un
reemplazo directo para la fecha y hora nativa de Python, por lo que todos los métodos que se pueden
aplicar a Python también se pueden aplicar a Pendulum. Al igual que puede hacer datetime.now().year,
obtiene el mismo resultado con pendulum.now().year.
Listado 4.2 Comportamiento del péndulo igual a la fecha y hora nativa de Python
>>> péndulo.ahora().año
2020
La URL de páginas vistas de Wikipedia requiere meses, días y horas con ceros (p. ej., "07" para la hora
7). Dentro de la cadena con plantilla Jinja, por lo tanto, aplicamos ting de formato de cadena para el
relleno:
{{ '{:02}'.formato(fecha_ejecución.hora) }}
Tenga en cuenta que los elementos en template_fields son nombres de atributos de clase. Por lo
general, los nombres de los argumentos proporcionados a __init__ coinciden con los nombres de
los atributos de clase, por lo que todo lo que se enumera en template_fields se asigna 1:1 a los
argumentos de __init__ . Sin embargo, técnicamente es posible que no lo hagan, y debe
documentarse qué atributo de clase asigna un argumento.
Machine Translated by Google
dag =
DAG( dag_id="chapter4_print_context",
start_date=airflow.utils.dates.days_ago(3),
schedule_interval="@daily",
)
def _print_context(**kwargs):
imprimir (kwargs)
print_context =
PythonOperator( task_id="print_context",
python_callable=_print_context, dag=dag,
Ejecutar esta tarea imprime un dictado de todas las variables disponibles en el contexto de la tarea.
Listado 4.4 Todas las variables de contexto para la fecha de ejecución dada
{
'dag': <DAG: print_context>, 'ds':
'2019-07-04', 'next_ds': '2019-07-04',
'next_ds_nodash': '20190704', 'prev_ds':
'2019-07 -03', 'prev_ds_nodash':
'20190703',
...
}
Todas las variables se capturan en **kwargs y se pasan a la función print() . Todas estas variables están disponibles
en tiempo de ejecución. La Tabla 4.1 proporciona una descripción de todas las variables de contexto de tareas
disponibles.
Machine Translated by Google
Impreso con PythonOperator ejecutado manualmente en un DAG con fecha de ejecución 2019-01-01T00:00:00, @intervalo diario.
dag = dag(
dag_id="stocksense",
start_date=airflow.utils.dates.days_ago(1),
intervalo_de_horario="@por hora",
)
def _get_data(ejecución_fecha):
año, mes, día, hora, *_ = fecha_ejecución.timetuple()
dirección URL = (
"https://dumps.wikimedia.org/other/pageviews/" el pitón
f"{año}/{año}-{mes:0>2}/" El operador toma un
f”páginas vistas-{año}{mes:0>2}{día:0>2}-{hora:0>2}0000.gz" función de Python,
) mientras que la
ruta_salida = "/tmp/wikipageviews.gz" BashOperator
request.urlretrieve(url, ruta_de_salida) toma un
comando Bash como un
cadena a ejecutar.
get_data = OperadorPython(
task_id="obtener_datos",
python_callable=_get_data, dag=dag,
Las funciones son ciudadanos de primera clase en Python, y proporcionamos un callable2 (una función es un
objeto invocable) al argumento python_callable de PythonOperator. En la ejecución, PythonOperator ejecuta
la llamada proporcionada, que podría ser cualquier función. Dado que es una función, y no una cadena
como con todos los demás operadores, el código dentro
la función no se puede crear una plantilla automáticamente. En cambio, las variables de contexto de la tarea
se pueden proporcionar y utilizar en la función dada, como se muestra en la figura 4.5.
OperadorPython(
task_id="contraseña_contexto",
python_callable=_contraseña_contexto,
2
En Python, cualquier objeto que implemente __call__() se considera invocable (por ejemplo, funciones/métodos).
Machine Translated by Google
(continuado)
provide_context=Verdadero,
dag=dag,
)
PythonOperator( task_id="pass_context",
python_callable=_pass_context, dag=dag,
Para mantener la compatibilidad con versiones anteriores, el argumento provide_context aún se admite
en Airflow 2; sin embargo, puede eliminarlo de manera segura cuando se ejecuta en Airflow 2.
Python permite capturar argumentos de palabras clave en una función. Esto tiene varios casos de uso,
principalmente si no conoce los argumentos de palabras clave proporcionados por adelantado y para evitar
tener que escribir explícitamente todos los nombres de argumentos de palabras clave esperados.
Machine Translated by Google
Listado 4.7 Cambiar el nombre de kwargs a contexto para expresar la intención de almacenar el contexto de la tarea
print_context = OperadorPython(
task_id="imprimir_contexto",
python_callable=_imprimir_contexto,
dag = dag,
)
La variable de contexto es un dict de todas las variables de contexto, lo que nos permite dar nuestra tarea
comportamiento diferente para el intervalo en el que se ejecuta, por ejemplo, para imprimir el inicio y el final
fecha y hora del intervalo actual:
def _print_context(**contexto):
inicio = contexto["fecha_ejecución"] fin = Extraiga la fecha_ejecución del
contexto["fecha_próxima_ejecución"] contexto.
print(f"Inicio: {inicio}, fin: {fin}")
print_context = OperadorPython(
task_id="imprimir_contexto", python_callable=_imprimir_contexto, dag=dag
)
Ahora que hemos visto algunos ejemplos básicos, vamos a diseccionar el PythonOperator descargando las
vistas de página de Wikipedia por hora como se ve en el listado 4.5 (figura 4.6).
La función _get_data llamada por PythonOperator toma un argumento:
**contexto. Como hemos visto antes, podríamos aceptar todos los argumentos de palabras clave en un solo
argumento denominado **kwargs (el doble asterisco indica todos los argumentos de palabras clave y
kwargs es el nombre de la variable real). Para indicar que esperamos variables de contexto de tareas,
podríamos cambiarle el nombre a **contexto. Sin embargo, hay otra forma en Python de aceptar argumentos
de palabras clave.
Machine Translated by Google
def _get_data(**contexto):
año, mes, día, hora, *_ = context["execution_date"].timetuple() url = ( "https://
dumps.wikimedia.org/other/pageviews/" f"{year}/{year}- {mes:0>2}/páginas vistas-{año}
{mes:0>2}{día:0>2}-{hora:0>2}0000.gz"
) ruta_salida = "/tmp/wikipageviews.gz"
solicitud.urlretrieve(url, ruta_salida)
Figura 4.6 PythonOperator toma una función en lugar de argumentos de cadena y, por lo tanto, no puede
tener una plantilla de Jinja. En esta función llamada, extraemos componentes de fecha y hora de la fecha_ejecución
para construir dinámicamente la URL.
Lo que sucede bajo el capó es que se llama a la función _get_data con todas las variables de contexto
como argumentos de palabras clave:
Listado 4.10 Todas las variables de contexto se pasan como argumentos de palabras clave
Python comprobará entonces si se espera alguno de los argumentos dados en la firma de la función
(figura 4.7).
El primer argumento conf se verifica y no se encuentra en la firma (argumentos esperados) de
_get_data y, por lo tanto, se agrega a **context. Esto se repite para dag y
¿fecha_ejecución en la firma?
En caso afirmativo, pase al argumento.
El resultado final con este ejemplo es que una palabra clave con el nombre de fecha_ejecución
se pasa al argumento fecha_ejecución y todas las demás variables se pasan a **contexto ya
que no se esperan explícitamente en la firma de la función (figura 4.9).
Figura 4.9 Se puede dar cualquier argumento con nombre a _get_data(). la fecha_ejecución
debe proporcionarse explícitamente porque aparece como un argumento, todos los demás
argumentos son capturados por **contexto.
admitir una segunda fuente de datos. El PythonOperator, sin embargo, también admite el suministro
argumentos adicionales a la función invocable. Por ejemplo, supongamos que comenzamos haciendo el
output_path configurable, de forma que, dependiendo de la tarea, podamos configurar la salida
_path en lugar de tener que duplicar toda la función solo para cambiar la ruta de salida
(figura 4.10).
"https://dumps.wikimedia.org/other/pageviews/"
f"{año}/{año}-{mes:0>2}/páginas vistas-{año}{mes:0>2}{día:0>2}-{hora:0>2}0000.gz"
)
request.urlretrieve(url, ruta_de_salida)
get_data = OperadorPython(
task_id="obtener_datos", Proporcione variables
adicionales al invocable con
python_callable=_get_data,
op_args=["/tmp/wikipageviews.gz"], dag=dag, op_args.
get_data = OperadorPython(
task_id="obtener_datos", Un dict dado a
python_callable=_get_data, op_kwargs se pasará
op_kwargs={"output_path": "/tmp/wikipageviews.gz"}, dag=dag, como argumentos de
palabra clave al
invocable.
)