web-dev-qa-db-fra.com

Airflow - fichier Python PAS dans le même dossier DAG

J'essaie d'utiliser Airflow pour exécuter une tâche simple python. 

from __future__ import print_function
from airflow.operators.python_operator import PythonOperator
from airflow.models import DAG
from datetime import datetime, timedelta


from pprint import pprint

seven_days_ago = datetime.combine(datetime.today() - timedelta(7),
                                  datetime.min.time())

args = {
    'owner': 'airflow',
    'start_date': seven_days_ago,
}

dag = DAG(dag_id='python_test', default_args=args)


def print_context(ds, **kwargs):
    pprint(kwargs)
    print(ds)
    return 'Whatever you return gets printed in the logs'

run_this = PythonOperator(
    task_id='print',
    provide_context=True,
    python_callable=print_context,
    dag=dag)

Si j'essaye, par exemple: 

test de débit d'air python_test print 01/01/2015

Ça marche!

Maintenant, je veux mettre ma fonction def print_context(ds, **kwargs) dans un autre fichier Python. Donc, je crée un fichier antoher appelé: simple_test.py et change:

run_this = PythonOperator(
    task_id='print',
    provide_context=True,
    python_callable=simple_test.print_context,
    dag=dag)

Maintenant j'essaie de courir à nouveau: 

test de débit d'air python_test print 01/01/2015

Et bien! Ça marche encore!

Mais si je crée un module, par exemple un module utilisateur avec le fichier SimplePython.py, importez-le (from worker import SimplePython) et essayez: 

test de débit d'air python_test print 01/01/2015

Cela donne le message: 

ImportError: Aucun module nommé worker

Questions:

  1. Est-il possible d'importer un module dans une définition de DAG?
  2. Comment Airflow + Celery va-t-il distribuer tous les fichiers sources Python nécessaires sur les nœuds de travail?
9
p.magalhaes

Vous pouvez créer des dépendances de votre DAG selon:

https://airflow.Apache.org/concepts.html#packaged-dags

Pour permettre cela, vous pouvez créer un fichier Zip contenant le (s) dag (s) à la racine du fichier Zip et décompresser les modules supplémentaires dans des répertoires. Par exemple, vous pouvez créer un fichier Zip ressemblant à ceci:

my_dag1.py
my_dag2.py
package1/__init__.py
package1/functions.py

Airflow analysera le fichier Zip et essaiera de charger my_dag1.py et my_dag2.py. Il ne sera pas placé dans les sous-répertoires, ceux-ci étant considérés comme des packages potentiels.

Lorsque vous utilisez CeleryExecutor, vous devez synchroniser manuellement les répertoires DAG, Airflow ne s'en occupe pas pour vous:

https://airflow.Apache.org/configuration.html?highlight=scaling%20out%20celery#scaling-out-with-celery

L'utilisateur doit avoir accès à son fichier DAGS_FOLDER et vous devez synchroniser les systèmes de fichiers par vos propres moyens.

6
ImDarrenG

Pour votre première question, c'est possible. 

Et je suppose que vous devriez créer un fichier vide nommé __init__.py dans le même répertoire que SimplePython.py (il s'agit du répertoire worker dans votre cas). En faisant cela, le répertoire worker sera considéré comme un module python.

Ensuite, dans votre définition de DAG, essayez from worker.SimplePython import print_context.

Dans votre cas, il serait préférable que vous écriviez un plug-in pour la ventilation, car vous voudrez peut-être mettre à niveau le projet principal de la ventilation sans supprimer vos fonctions personnalisées.

1
Yongyiw

Pour votre deuxième question: Comment Airflow + Celery va-t-il distribuer tous les fichiers sources Python nécessaires sur les nœuds de travail? 

À partir de la documentation: le travailleur doit avoir accès à son DAGS_FOLDER et vous devez synchroniser les systèmes de fichiers par vos propres moyens. Une installation courante consisterait à stocker votre DAGS_FOLDER dans un référentiel Git et à le synchroniser sur des machines utilisant Chef, Puppet, Ansible ou tout ce que vous utilisez pour configurer des machines dans votre environnement. Si toutes vos boîtes ont un point de montage commun, le partage de vos fichiers de pipeline devrait également fonctionner.

http://pythonhosted.org/airflow/installation.html?highlight=chef

1
nono

Tandis que l’emballage de vos dags dans un zip tel que couvert dans la documentation est la seule solution prise en charge que j’ai vue, vous pouvez également importer des modules qui se trouvent dans le dossier dags. Ceci est utile si vous synchronisez le dossier dags automatiquement à l'aide d'autres outils tels que marionnette et git.

Je ne comprends pas bien la structure de votre répertoire à partir de la question. Voici donc un exemple de dossier dags basé sur une structure de projet python typique:

└── airflow/dags  # root airflow dags folder where all dags live
    └── my_dags  # git repo project root
        ├── my_dags  # python src root (usually named same as project)
        │   ├── my_test_globals.py  # file I want to import
        │   ├── dag_in_package.py 
        │   └── dags 
        │        └── dag_in_subpackage.py
        ├── README.md  # also setup.py, LICENSE, etc here
        └── dag_in_project_root.py

J'ai omis les fichiers (requis [ 1 ]) __init__.py. Notez l'emplacement des trois exemples de dags. Vous utiliseriez presque certainement un seul de ces endroits pour tous vos dags. Je les inclut tous ici à titre d'exemple car cela ne devrait pas importer pour l'importation. Pour importer my_test_globals depuis l'un d'entre eux:

from my_dags.my_dags import my_test_globals

Je pense que cela signifie que airflow charge chaque sous-répertoire du dossier dags sous la forme d’un paquet Python . Dans mon cas, il s’agissait du répertoire racine supplémentaire du projet intermédiaire qui permettait de réaliser une importation absolue intra-package typique. Ainsi, nous pourrions restructurer ce projet de flux d’air comme ceci:

└── airflow/dags  # root airflow dags folder where all dags live
    └── my_dags  # git repo project root & python src root
        ├── my_test_globals.py  # file I want to import
        ├── dag_in_package.py 
        ├── dags 
        │    └── dag_in_subpackage.py
        ├── README.md  # also setup.py, LICENSE, etc here
        └── dag_in_project_root.py

Pour que les importations se présentent, nous nous attendons à:

from my_dags import my_test_globals
1
7yl4r