Python 有没有办法在“气流”中创建动态工作流

Python 有没有办法在“气流”中创建动态工作流,python,airflow,Python,Airflow,所以我有一个任务,就是将一些未知数量的文件复制到一个文件夹中。 任务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_th

所以我有一个任务,就是将一些未知数量的文件复制到一个文件夹中。 任务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)

我正在获取目录中所有文件的名称,然后为它们运行操作符,但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)测试了它,它似乎工作得很好


我不希望在DagRun处于活动状态时Airflow会修改DAG,因此我不会把钱押在获取文件然后在同一DAG中附加任务上。也就是说,气流每隔几秒钟就会再生一次DAG。可以使用一个DAG获取文件,另一个DAG处理这些文件。获取文件后,第一个DAG必须等待一分钟以确保气流被注意到,然后使用
触发器DAG运行器启动第二个DAG

DAG1:

DAG2:


与其说是一种解决方案,不如说是一种黑客手段,但类似的方法应该可以奏效。但是,外部触发器和动态任务存在问题。当我不得不使用
dependens\u past=True

时,我通常会遇到调度程序问题。您会遇到什么错误?不,它不需要事先知道任务的数量。它只需要在计划/运行dag加载新任务之前重新启动web服务器,是的,每个任务都应该有唯一的任务id。
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
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