Google Dataflow:导入自定义Python模块

时间:2020-01-13 13:12:04

标签: airflow google-cloud-dataflow apache-beam google-cloud-composer

我尝试由Google Cloud Coomposer中的DAG触发,在Google Cloud Dataflow中运行Apache Beam管道(Python)。

我的dags文件夹在相应的GCS存储桶中的结构如下:

/dags/
  dataflow.py <- DAG
  dataflow/
    pipeline.py <- pipeline
    setup.py
    my_modules/
      __init__.py
      commons.py <- the module I want to import in the pipeline

setup.py是非常基本的,但是根据Apache Beam的文档和答案:

import setuptools

setuptools.setup(setuptools.find_packages())

在DAG文件(dataflow.py)中,设置setup_file选项并将其传递给Dataflow:

default_dag_args = {
    ... ,
    'dataflow_default_options': {
        ... ,
        'runner': 'DataflowRunner',
        'setup_file': os.path.join(configuration.get('core', 'dags_folder'), 'dataflow', 'setup.py')
    }
}

我尝试使用的管道文件(pipeline.py)

from my_modules import commons

但是失败了。 Google Cloud Composer(Apache Airflow)中的日志显示:

gcp_dataflow_hook.py:132} WARNING - b'  File "/home/airflow/gcs/dags/dataflow/dataflow.py", line 11\n    from my_modules import commons\n           ^\nSyntaxError: invalid syntax'

setup.py文件背后的基本思想记录在here

另外,关于SO的类似问题也对我有帮助:

Google Dataflow - Failed to import custom python modules

Dataflow/apache beam: manage custom module dependencies

我实际上是在想为什么我的管道失败并出现Syntax Error而不是module not found的错误...

1 个答案:

答案 0 :(得分:1)

我试图重现您的问题,然后尝试解决它,所以我创建了与您已经拥有的文件夹结构相同的文件

/dags/
  dataflow.py
  dataflow/
     pipeline.py -> pipeline
     setup.py
     my_modules/
        __init__.py
        common.py

因此,要使其正常工作,我所做的更改是将这些文件夹复制到实例正在运行的位置,例如,在实例的/tmp/文件夹中,代码可以找到它。 / p>

所以,我的DAG应该是这样的:

1-我首先宣布自己的论点:

default_args = {
   'start_date': datetime(xxxx, x, x),
   'retries': 1,
   'retry_delay': timedelta(minutes=5),
   'dataflow_default_options': {
       'project': '<project>',
       'region': '<region>',
       'stagingLocation': 'gs://<bucket>/stage',
       'tempLocation': 'gs://<bucket>/temp',
       'setup_file': <setup.py>,
       'runner': 'DataflowRunner'
   }
} 

2-之后,我创建了DAG,然后在运行数据流任务之前,将上面创建的整个文件夹目录复制到实例/tmp/的{​​{1}}文件夹中,然后,我从/ tmp /目录Task t1运行管道:

Task t2

这就是我创建DAG文件with DAG( 'composer_df', default_args=default_args, description='datflow dag', schedule_interval="xxxx") as dag: def copy_dependencies(): process = subprocess.Popen(['gsutil','cp', '-r' ,'gs://<bucket>/dags/*', '/tmp/']) process.communicate() t1 = python_operator.PythonOperator( task_id='copy_dependencies', python_callable=copy_dependencies, provide_context=False ) t2 = DataFlowPythonOperator(task_id="composer_dataflow", py_file='/tmp/dataflow/pipeline.py', job_name='job_composer') t1 >> t2 的方式,然后在dataflow.py中导入的包如下:

pipeline.py

应该正常工作,因为VM可以理解文件夹目录。