dosya adlarına göre üst veri tabanından dinamik alt veriler oluşturmaya çalışmak


10

Hava akışı kullanarak GCS için "silinmeyen" bir kova (yani dosyaları silemezsiniz) s3 dosyaları taşımak için çalışıyorum. Yeni dosyaların her gün orada olacağı garanti edilemez, ancak her gün yeni dosyaları kontrol etmeliyim.

benim sorunum, alt verilerin dinamik oluşturulmasıdır. ARE dosyaları varsa, alt günlüklere ihtiyacım var. NOT dosyaları yoksa, alt günlüklere ihtiyacım yok. Benim sorunum yukarı / aşağı ayarlarıdır. Kodumda dosyaları algılar, ancak olması gerektiği gibi alt verileri başlatmaz. Bir şey eksik.

İşte benim kod:

from airflow import models
from  airflow.utils.helpers import chain
from airflow.providers.amazon.aws.hooks.s3 import S3Hook
from airflow.operators.python_operator import PythonOperator, BranchPythonOperator
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.subdag_operator import SubDagOperator
from airflow.contrib.operators.s3_to_gcs_operator import S3ToGoogleCloudStorageOperator
from airflow.utils import dates
from airflow.models import Variable
import logging

args = {
    'owner': 'Airflow',
    'start_date': dates.days_ago(1),
    'email': ['sinistersparrow1701@gmail.com'],
    'email_on_failure': True,
    'email_on_success': True,
}

bucket = 'mybucket'
prefix = 'myprefix/'
LastBDEXDate = int(Variable.get("last_publish_date"))
maxdate = LastBDEXDate
files = []

parent_dag = models.DAG(
    dag_id='My_Ingestion',
    default_args=args,
    schedule_interval='@daily',
    catchup=False
)

def Check_For_Files(**kwargs):
    s3 = S3Hook(aws_conn_id='S3_BOX')
    s3.get_conn()
    bucket = bucket
    LastBDEXDate = int(Variable.get("last_publish_date"))
    maxdate = LastBDEXDate
    files = s3.list_keys(bucket_name=bucket, prefix='myprefix/file')
    for file in files:
        print(file)
        print(file.split("_")[-2])
        print(file.split("_")[-2][-8:])  ##proves I can see a date in the file name is ok.
        maxdate = maxdate if maxdate > int(file.split("_")[-2][-8:]) else int(file.split("_")[-2][-8:])
    if maxdate > LastBDEXDate:
        return 'Start_Process'
    return 'finished'

def create_subdag(dag_parent, dag_id_child_prefix, file_name):
    # dag params
    dag_id_child = '%s.%s' % (dag_parent.dag_id, dag_id_child_prefix)

    # dag
    subdag = models.DAG(dag_id=dag_id_child,
              default_args=args,
              schedule_interval=None)

    # operators
    s3_to_gcs_op = S3ToGoogleCloudStorageOperator(
        task_id=dag_id_child,
        bucket=bucket,
        prefix=file_name,
        dest_gcs_conn_id='GCP_Account',
        dest_gcs='gs://my_files/To_Process/',
        replace=False,
        gzip=True,
        dag=subdag)


    return subdag

def create_subdag_operator(dag_parent, filename, index):
    tid_subdag = 'file_{}'.format(index)
    subdag = create_subdag(dag_parent, tid_subdag, filename)
    sd_op = SubDagOperator(task_id=tid_subdag, dag=dag_parent, subdag=subdag)
    return sd_op

def create_subdag_operators(dag_parent, file_list):
    subdags = [create_subdag_operator(dag_parent, file, file_list.index(file)) for file in file_list]
    # chain subdag-operators together
    chain(*subdags)
    return subdags

check_for_files = BranchPythonOperator(
    task_id='Check_for_s3_Files',
    provide_context=True,
    python_callable=Check_For_Files,
    dag=parent_dag
)

finished = DummyOperator(
    task_id='finished',
    dag=parent_dag
)

decision_to_continue = DummyOperator(
    task_id='Start_Process',
    dag=parent_dag
)

if len(files) > 0:
    subdag_ops = create_subdag_operators(parent_dag, files)
    check_for_files >> decision_to_continue >> subdag_ops[0] >> subdag_ops[-1] >> finished


check_for_files >> finished

Bu DAG arka uç en iş ishal çeşitleri nelerdir bunlar sparkişler ya da bazı pythonkomut ve ne gibi çalıştırmak için kullandığınız livyveya başka bir yöntem
ashwin agrawal

Üzgünüm, soruyu anlamıyorum. lütfen geri dönebilir misin
arcee123

Yani basit bir python betikleri kullanıyorsunuz ve herhangi bir kıvılcım işi kullanmıyorsunuz değil mi?
ashwin agrawal

Evet. hava akışında varsayılan basit operatörler. GCS içine almak istiyorum S3 işaretli dosyalara dayalı dinamik bir hızda mevcut operatörleri eklemek istiyorum.
arcee123

Neden filesboş bir liste?
Oluwafemi Sule

Yanıtlar:


3

Aşağıda, hava akışında dinamik bir DAG veya alt DAG oluşturmanın önerilen yolu da vardır, ancak başka yollar da vardır, ancak sanırım bu büyük ölçüde probleminiz için geçerli olacaktır.

İlk olarak, (yaml/csv)tüm s3dosyaların ve konumların listesini içeren bir dosya oluşturun, bunları listede saklamak için bir işlev yazdıysanız, bunları ayrı bir yamldosyada saklayın ve hava akımı env'de çalışma zamanında yükleyin ve ardından oluşturun DAG'ler.

Aşağıda örnek bir yamldosya bulunmaktadır: dynamicDagConfigFile.yaml

job: dynamic-dag
bucket_name: 'bucket-name'
prefix: 'bucket-prefix'
S3Files:
    - File1: 'S3Loc1'
    - File2: 'S3Loc2'
    - File3: 'S3Loc3'

Check_For_FilesBir yamldosyada saklamak için işlevinizi değiştirebilirsiniz .

Şimdi dinamik dag oluşturmaya geçebiliriz:

İlk olarak, başlangıç ​​ve bitiş görevi olmak üzere, kukla işleçleri kullanarak iki görev tanımlayın. Bu tür görevler, DAGaralarında dinamik olarak görevler oluşturarak bizim üzerine inşa edeceğimiz görevlerdir:

start = DummyOperator(
    task_id='start',
    dag=dag
)

end = DummyOperator(
    task_id='end',
    dag=dag)

Dinamik DAG: PythonOperatorsHava akışında kullanacağız . İşlev argüman olarak görev kimliğini almalıdır; yürütülecek bir python işlevi, yani Python operatörü için python_callable; ve yürütme sırasında kullanılacak bir dizi argüman.

Bir argüman ekleyin task id. Böylece, dinamik yolla oluşturulan görevler arasında veri alışverişi yapabiliriz, örn XCOM.

Bu dinamik veri alanı içinde çalışma işlevinizi belirtebilirsiniz s3_to_gcs_op.

def createDynamicDAG(task_id, callableFunction, args):
    task = PythonOperator(
        task_id = task_id,
        provide_context=True,
        #Eval is used since the callableFunction var is of type string
        #while the python_callable argument for PythonOperators only receives objects of type callable not strings.
        python_callable = eval(callableFunction),
        op_kwargs = args,
        xcom_push = True,
        dag = dag,
    )
    return task

Son olarak yaml dosyasındaki konuma bağlı olarak dinamik veriler oluşturabilir, önce yamldosyayı aşağıdaki gibi okuyabilir ve dinamik veriler oluşturabilirsiniz:

with open('/usr/local/airflow/dags/config_files/dynamicDagConfigFile.yaml') as f:
    # use safe_load instead to load the YAML file
    configFile = yaml.safe_load(f)

    #Extract file list
    S3Files = configFile['S3Files']

    #In this loop tasks are created for each table defined in the YAML file
    for S3File in S3Files:
        for S3File, fieldName in S3File.items():

            #Remember task id is provided in order to exchange data among tasks generated in dynamic way.
            get_s3_files = createDynamicDAG('{}-getS3Data'.format(S3File), 
                                            'getS3Data', 
                                            {}) #your configs here.

            #Second step is upload S3 to GCS
            upload_s3_toGCS = createDynamicDAG('{}-uploadDataS3ToGCS'.format(S3File), 'uploadDataS3ToGCS', {'previous_task_id':'{}-'})

#write your configs again here like S3 bucket name prefix extra or read from yaml file, and other GCS config.

Son DAG tanımı:

Fikir şu ki

#once tasks are generated they should linked with the
#dummy operators generated in the start and end tasks. 
start >> get_s3_files
get_s3_files >> upload_s3_toGCS
upload_s3_toGCS >> end

Tam hava akışı kodu sırayla:

import yaml
import airflow
from airflow import DAG
from datetime import datetime, timedelta, time
from airflow.operators.python_operator import PythonOperator
from airflow.operators.dummy_operator import DummyOperator

start = DummyOperator(
    task_id='start',
    dag=dag
)


def createDynamicDAG(task_id, callableFunction, args):
    task = PythonOperator(
        task_id = task_id,
        provide_context=True,
        #Eval is used since the callableFunction var is of type string
        #while the python_callable argument for PythonOperators only receives objects of type callable not strings.
        python_callable = eval(callableFunction),
        op_kwargs = args,
        xcom_push = True,
        dag = dag,
    )
    return task


end = DummyOperator(
    task_id='end',
    dag=dag)



with open('/usr/local/airflow/dags/config_files/dynamicDagConfigFile.yaml') as f:
    configFile = yaml.safe_load(f)

    #Extract file list
    S3Files = configFile['S3Files']

    #In this loop tasks are created for each table defined in the YAML file
    for S3File in S3Files:
        for S3File, fieldName in S3File.items():

            #Remember task id is provided in order to exchange data among tasks generated in dynamic way.
            get_s3_files = createDynamicDAG('{}-getS3Data'.format(S3File), 
                                            'getS3Data', 
                                            {}) #your configs here.

            #Second step is upload S3 to GCS
            upload_s3_toGCS = createDynamicDAG('{}-uploadDataS3ToGCS'.format(S3File), 'uploadDataS3ToGCS', {'previous_task_id':'{}-'})

#write your configs again here like S3 bucket name prefix extra or read from yaml file, and other GCS config.


start >> get_s3_files
get_s3_files >> upload_s3_toGCS
upload_s3_toGCS >> end

Çok teşekkür ederim. yani yaşadığım sorunlardan biri yeni dosya yoksa ne olacaktı? Karşılaştığım sorunlardan biri, bu yerde her zaman dosyalar olacak, ancak çekilecek yeni dosyaların garanti edilmeyeceği, bu bölümün upload_s3_toGCSolmayacağı ve hava akışında hata olduğu anlamına geliyor .
arcee123

yamlTüm bu dosyalar GCS'ye yüklendikten sonra dosyaları dosyadan kaldırarak sorunu çözebilirsiniz, bu şekilde dosyada sadece yeni dosyalar bulunur yaml. Ve yeni dosya yoksa, yamldosya boş olacak ve dinamik veri oluşturulmaz. Bu yüzden yamldosya, bir listede dosya depolamaya kıyasla çok daha iyi bir seçenektir.
ashwin agrawal

yamlDosyası da s3 dosyanın bazı varsayalım eğer, bir bakıma s3 dosyalarının günlüğü korunmasında yardımcı ise, o dosyaya karşılık gelen bir bayrak koruyabilirsiniz, GCS yüklenmesine başarısız ve sonraki DAG çalışma zamanında bu yeniden deneyecek.
ashwin agrawal

Yeni dosya yoksa if, DAG'dan önce yamlyeni dosyalar yürütülürse dosyalarda yeni dosyaları kontrol edecek bir koşul koyabilirsiniz, aksi takdirde dosyayı atlayın.
ashwin agrawal

buradaki sorun, aşağı akışların ayarlanmış olmasıdır. aşağı akımlar gerçek işler olmadan ayarlanırsa (dosya olmadığı için) hata verir.
arcee123
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.