繁体   English   中英

如何在气流中准确生成一次 datetime.now()

[英]How to generate datetime.now() in airflow exactly one time

当我尝试根据name + current date生成唯一名称时出现错误。

NAME = 'name-{timestamp}'.format(timestamp=datetime.now())

但是每个任务实例再次生成datetime.now()并且每个任务的NAME变得不同。

task1 = CustomOperator(
    task_id='task-1',
    name = NAME,
    ...
)

task2 = CustomOperator(
    task_id='task-2',
    name = NAME,
    ...
)

task1task2里面的NAME会不同。 我需要NAME是唯一的,并且可以从 DAG 中的任务实例进行全局访问。 有什么建议?

气流任务预计是静态的或缓慢变化的。 Airflow 每隔min_file_process_interval (默认 30 秒)解析 DAG 文件 - 这意味着每 30 秒您将创建一个新任务 - 甚至可能不会运行。

很难理解为什么要创建这样的任务,因为您没有解释您的用例,但是如果您需要动态任务,您可以这样做:

for i in range(0, 5):
    DummyOperator(task_id='{0}'.format(i))

编辑:现在您编辑了您的问题并进行了更好的解释。 name 参数是您的 Operator 的一些自定义参数。 它可以是任何你想要的。 你可以做什么:

timestamp = datetime.now()
for i in range(1, 3):
    task_id = f'task_{i}'
    CustomOperator(task_id=task_id, name=f'{task_id}_{str(timestamp)}')

请注意,虽然这将为您提供独特的值,但您很难跟踪它们。 一种更好、更 Airflowy 的方法是使用{{ execution_date }} ,它假设name模板化字段:

for i in range(1, 3):
    task_id = f'task_{i}'
    CustomOperator(task_id=task_id, name=f'{task_id}_{{{{ execution_date }}}}')

或者您可以使用{{ task_instance_key_str }}宏,它是格式为{dag_id}__{task_id}__{ds_nodash}的任务实例的唯一的、人类可读的键

for i in range(1, 3):
    task_id = f'task_{i}'
    CustomOperator(task_id=task_id, name='{{ task_instance_key_str }}')

正如Elad和其他评论者所建议的那样,您可能想要这个。 也许您应该在execute方法中生成和记录/发出此信息。

尽管如此,对于跨不同领域、任务和编程语言的编程新手来说,这是一个非常常见的“陷阱”,因此我认为如果仅出于教学目的,这里展示该模式是值得的。

答案很简单:计算一次的时间,并将其保存在一个变量。 就是这样。 就这么简单。 这实际上就是变量的用途。

我还强烈建议使用datetime.strftime方法显式格式化时间戳,而不是依赖str()为您隐式地完成它。 盲目str -ifying东西是另一个经典的新手的错误。

最后,使用时区感知 datetimes ,并使用 UTC 不要想太多。 去做就对了。 以后你会感谢我的。

完整示例:

from __future__ import annotations
import sys
from datetime import datetime, timezone
from typing import Any
if sys.version_info < (3, 9):
    from typing import Dict
else:
    Dict = dict

from airflow import DAG
from airflow.models.baseoperator import BaseOperator


# Define a custom operator

class MyOperator(BaseOperator):
    """A custom Airflow operator that doesn't really do anything."""
    def __init__(self, task_id: str, name: str, **kwargs) -> None:
        self.task_id = task_id
        self.name = name
        super().__init__(**kwargs)

    def execute(self, context: Dict[str, Any]) -> int:
        print(
            f'Hello, I am {self.name}, '
            f'and I am executing Task ID {self.task_id}.'
        )
        return len(context)


# Pre-compute the time, making sure to use UTC.
now = datetime.now(timezone.utc)

# Format the time, unambiguously.
now_fmt = now.strftime('%Y-%m-%d_%H:%M:%S%z')

# Another option for formatting.
# See:
# * https://docs.python.org/3/library/datetime.html#datetime.datetime.isoformat
# * https://en.wikipedia.org/wiki/ISO_8601
# * https://datatracker.ietf.org/doc/html/rfc3339
# now_fmt = now.isoformat()

# Use the formatted time string as many times as you need.
with DAG(...) as dag:
    task1 = MyOperator(
        task_id='task-1',
        name = f'task-1_{now_fmt}',
        ...
    )

    task2 = MyOperator(
        task_id='task-2',
        name = f'task-2_{now_fmt},
        ...
    )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM