所以我有任务A,它将一些未知数量的文件复制到文件夹中。 任务B在文件夹中的每个文件上运行。由于文件不断变化,我无法事先知道文件数量。有没有办法使这种工作在气流中进行。
spans = os.listdir('/home/abc/tmpFolder')
counter = 0
for s in spans:
src_path = '/home/abc/tmpFolder' + s
dst_path = "tmp/" + s
counter += 1
run_this = \
FileToGoogleCloudStorageOperator(
task_id='gcp_task_' + str(counter),
src=src_path,
dst=dst_path,
bucket='gcpBucket',
google_cloud_storage_conn_id='gcp',
mime_type='text/plain',
dag=dag
)
dummy_operator_two.set_downstream(run_this)
我正在获取目录中所有文件的名称,然后为它们运行运算符,但是气流无法正常工作,因为它需要事先知道编号。
答案 0 :(得分:1)
在DagRun处于活动状态时,我不希望Airflow修改DAG,因此我不会押注于获取文件然后在同一DAG中附加任务。话虽如此,Airflow每隔几秒钟就会重新生成DAG。您可能有一个DAG可以获取文件,而另一个DAG可以处理这些文件。获取文件后,第一个DAG必须等待一分钟以确保注意到Airflow,然后使用TriggerDagRunOperator
启动第二个DAG。
DAG1:
def wait_a_minute():
time.sleep(60)
get_files = DummyOperator(dag=dag, task_id='get_files')
give_airflow_time_to_rebuild_DAG2 = PythonOperator(dag=dag, task_id='give_airflow_time_to_rebuild_DAG2', python_callable=wait_a_minute)
trigger_DAG2 = TriggerDagRunOperator(dag=dag, task_id='trigger_DAG2', trigger_dag_id='DAG2', execution_date='{{ ds }}')
get_files >> give_airflow_time_to_rebuild_DAG2 >> trigger_DAG2
DAG2:
pre_process = DummyOperator(dag=dag, task_id='pre_process')
post_process = DummyOperator(dag=dag, task_id='post_process')
files = get_files_to_process()
for file in files:
process = DummyOperator(dag=dag, task_id=f'process_{file}')
pre_process >> process >> post_process
hack比解决方案更多,但是类似的事情应该起作用。但是,外部触发器和动态任务存在问题。当我不得不使用depends_on_past=True
时,通常会遇到调度程序问题。
答案 1 :(得分:0)
我通过创建单独的管道而不是单独的任务来使这种事情起作用。
答案 2 :(得分:0)
您是否尝试过使用glob module并修改管道以处理给定目录中的所有文件?
答案 3 :(得分:0)
关于my blog post on Creating a Dynamic Workflow using Apache Airflow,您可以测试以下代码:
import airflow
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.bash_operator import BashOperator
from airflow.contrib.operators.file_to_gcs import FileToGoogleCloudStorageOperator
from datetime import datetime,timedelta
from os import listdir
default_args = {
'owner': 'test',
'depends_on_past': False,
'start_date': airflow.utils.dates.days_ago(1),
'retries': 1,
'retry_delay': timedelta(minutes=5)
}
dag = DAG('dynamic',
default_args=default_args,
description='Dynamic DAG',
schedule_interval=timedelta(days=1))
copy_files = BashOperator(task_id='cp_files',
depends_on_past=False,
bash_command='cp /tmp/filetocopy/* /tmp/filetoprocess',
dag=dag)
start = DummyOperator(task_id='start',
dag=dag)
end = DummyOperator(task_id='end',
dag=dag)
start >> copy_files
spans = listdir('/tmp/filetoprocess')
counter = 1
for s in spans:
src_path = '/tmp/filetoprocess/' + s
dst_path = "/tmp/dest/" + s
counter += 1
task = FileToGoogleCloudStorageOperator(
task_id='gcp_task_' + str(counter),
src=src_path,
dst=dst_path,
bucket='gcpBucket',
google_cloud_storage_conn_id='gcp',
mime_type='text/plain',
dag=dag)
task.set_upstream(copy_files)
task.set_downstream(end)
使用此代码,您需要在/tmp/filetoprocess
文件夹中已经有一些文件(也可以创建一个Python函数来检查是否有一些文件,否则创建一个DummyOperator只是为了使整个工作流程正常工作) ;否则,气流调度程序将无法生成正确的DAG。
我已经在新的Apache Airflow版本(v.1.10)中对其进行了测试,它似乎运行得很好。