如何在Airflow操作员中打印唯一消息?

时间:2018-09-03 06:18:19

标签: python airflow

在气流中,可以使用简单的print()或建议的记录器here来记录日志

但是,当尝试在操作员内部进行打印时,这将不起作用。

我有以下代码:

for i in range(5, 0, -1):
    gcs_export_uri_template = ["adstest/{{ macros.ds_format(macros.ds_add(ds, -params.i), '%Y-%m-%d', '%Y/%m/%d') }}/*"]
    update_bigquery = GoogleCloudStorageToBigQueryOperator(
        dag=dag,
        task_id='load_ads_to_BigQuery-{}'.format(i),
        bucket=GCS_BUCKET_ID,
        destination_project_dataset_table=table_name_template,
        source_format='CSV',
        source_objects=gcs_export_uri_template,
        schema_fields=dc(),
        params={'i': i},
        create_disposition='CREATE_IF_NEEDED',
        write_disposition='WRITE_APPEND',
        skip_leading_rows=1,
        google_cloud_storage_conn_id=CONNECTION_ID,
        bigquery_conn_id=CONNECTION_ID
    )

现在说我想打印"My name is load_ads_to_BigQuery-{}".format{i) 如您所见,每个操作员的打印件都是统一的。

如果我这样做的话:

for i in range(5, 0, -1):
    print("My name is load_ads_to_BigQuery-{}".format{i))
    gcs_export_uri_template = ...
    update_bigquery = GoogleCloudStorageToBigQueryOperator(...)

所有5个操作员将打印所有5张照片。在我看来,这是不正确的。 打印件必须在GoogleCloudStorageToBigQueryOperator内。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

一个可能足够的解决方案是创建一个包装器类。示例:

class MyGoogleCloudStorageToBigQueryOperator(BaseOperator):
    template_fields = ('bucket', 'source_objects',
                   'schema_object', 'destination_project_dataset_table')

    @apply_defaults
    def __init__(self,
          bucket,
          destination_project_dataset_table,
          source_format,
          source_objects,
          schema_fields,
          params,
          create_disposition,
          write_disposition,
          skip_leading_rows,
          google_cloud_storage_conn_id,
          bigquery_conn_id,
          *args,
          **kwargs):
     super(InfogroupFilestreamOperator, self).__init__(*args, **kwargs)
     self.bucket= bucket
     self.destination_project_dataset_table=destination_project_dataset_table
     ...

  def execute(self, context):
      self.log.info("My name is %s", self.task_id)
      hook=GoogleCloudStorageToBigQueryOperator(
            task_id="doesnt_matter",
            bucket=self.bucket,             
            source_format=self.source_format,
            ...
            )

     return hook.execute(context)
然后可以实例化

MyGoogleCloudStorageToBigQueryOperator而不是for循环中的GoogleCloudStorageToBigQueryOperator

答案 1 :(得分:1)

基于@judoole的答案,您可以直接扩展GoogleCloudStorageToBigQueryOperator

class MyGoogleCloudStorageToBigQueryOperator(LoggingMixin, GoogleCloudStorageToBigQueryOperator):

    def execute(self, context):
        self.logger.info('Inside task {task_id}'.format(task_id=context['task_id']))
        super().execute(context)

通常,您可以编写一个mixin类,该类将自动为各种操作员执行这种类型的日志记录。

class LogTaskExecutionMixin(object):

    def execute(self, context):
        self.logger.info('Inside task {task_id}'.format(task_id=context['task_id']))
        super().execute(context)

class MyGoogleCloudStorageToBigQueryOperator(
    LogTaskExecutionMixin, LoggingMixin, GoogleCloudStorageToBigQueryOperator
):
    pass

这两种方法的思想都是定义一个新的运算符,该运算符在执行之前会写一条日志消息,但在其他方面与您扩展的运算符相同。