Python 如何在Airflow operator中打印唯一消息?

Python 如何在Airflow operator中打印唯一消息?,python,airflow,Python,Airflow,在airflow中,可以使用简单的print()或建议的记录器写入日志 但是,当试图在操作员内部打印时,这将不起作用 我有以下代码: 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 = GoogleCloudSto

在airflow中,可以使用简单的
print()
或建议的记录器写入日志

但是,当试图在操作员内部打印时,这将不起作用

我有以下代码:

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
    )
现在,假设我想打印
“我的名字是load\u ads\u to\u BigQuery-{}”。格式{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个打印。这在我的情况下是不正确的。 打印内容必须位于Google CloudStorageToBigQueryOperator内


我该怎么做呢?

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

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

基于@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

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

您也可以使用BaseOperator的log方法在运算符内部登录,如so
self.log.info(“这是%s”,“有趣”)
。所有的打印语句都是在dag内完成的,还是for循环在自定义运算符内完成的?@judoole我不确定我是否理解您是在dag文件内打印的,还是在自建模块内打印的,在for循环中创建5
GoogleCloudStorageToBigQueryOperator
s?很抱歉,我没有回复。@judoole根本不打印。我想将打印添加到我的代码中。我想在GoogleCloudStorageToBigQueryOperator中打印。我认为这对所有操作员来说都是一个问题。你建议我用一个函数包装我的操作员,该函数将打印并执行操作员。我不认为我支持这一点:\n我提交了一张罚单为什么不支持
类MyGoogleCloudStorageToBigQueryOperator(GoogleCloudStorageToBigQueryOperator):传递
,重写
执行
,并调用
super()。执行(上下文)
?是的,我想这在这种情况下也同样有效。更好的解决方案。如果您想获得额外的分数,请随意编辑,或者自己回答。我会投赞成票。