在气流中,一切都应该是UTC(不受DST影响)。
但是,我们的工作流程基于受DST影响的时区提供服务。
示例场景:
有没有办法安排dags,以便它们在时间变化后的正确时间运行?
答案 0 :(得分:5)
脱离我的头顶:
如果您的计算机具有时区感知功能,请将DAG设置为以UTC时间上午8点和上午8点(UTC)运行。像0 11,12 * * *
这样的东西。让第一个任务成为ShortCircuit操作员。然后使用像pytz这样的东西来定位当前时间。如果它在您所需的时间内,请继续(IE:运行DAG)。否则,返回False。您每天只需要额外的2个额外任务,但只要您的计算机没有超载,延迟就应该是最小的。
草率的例子:
from datetime import datetime
from pytz import utc, timezone
# ...
def is8AM(**kwargs):
ti = kwargs["ti"]
curtime = utc.localize(datetime.utcnow())
# If you want to use the exec date:
# curtime = utc.localize(ti.execution_date)
eastern = timezone('US/Eastern') # From docs, check your local names
loc_dt = curtime.astimezone(eastern)
if loc_dt.hour == 8:
return True
return False
start_task = ShortCircuitOperator(
task_id='check_for_8AM',
python_callable=is8AM,
provide_context=True,
dag=dag
)
希望这是有帮助的
编辑:运行时错误,减去而不是添加。此外,由于如何启动运行,如果您希望它们在8时运行,您最终可能希望按小时计划安排7AM。
答案 1 :(得分:3)
我们使用了@apathyman解决方案,但是我们只使用了PythonOperator而不是ShortCircuit,如果它不是我们想要的那个小时就会失败,并且使用timedelta重试1小时。 这样我们每天只运行1次而不是2次。
并且计划间隔设置为仅在第一个小时运行
基本上,类似的东西(大多数代码取自上面的答案,谢谢@apathyman):
from datetime import datetime
from datetime import timedelta
from pytz import utc, timezone
def is8AM(**kwargs):
ti = kwargs["ti"]
curtime = utc.localize(datetime.utcnow())
# If you want to use the exec date:
# curtime = utc.localize(ti.execution_date)
eastern = timezone('US/Eastern') # From docs, check your local names
loc_dt = curtime.astimezone(eastern)
if loc_dt.hour == 8:
return True
exit("Not the time yet, wait 1 hour")
start_task = PythonOperator(
task_id='check_for_8AM',
python_callable=is8AM,
provide_context=True,
retries=1,
retry_delay=timedelta(hours=1),
dag=dag
)
答案 2 :(得分:1)
我相信我们只需要一个PythonOperator来处理这种情况。
如果DAG需要在DST TZ中运行(例如:America / New_York,欧洲/伦敦,澳大利亚/悉尼),那么下面是我可以考虑的解决方法步骤:
-4
。因此,时间安排*/10 11-13 * * 1-5
将转换为*/10 15-17 * * 1-5
+1
。因此,时间安排35 */4 * * *
将转换为35 3-23/4 * * *
+11
。因此,时间安排15 8,9,12,18 * * *
将转换为15 21,22,1,7 * * *
使用PythonOperator
在所有主要任务之前完成任务。此任务将检查当前时间是否在指定TZ的DST中。如果是,则任务将在1小时内休眠。
这样我们就可以处理DST TZ的情况。
def is_DST(zonename):
tz = pytz.timezone(zonename)
now = pytz.utc.localize(datetime.utcnow())
return now.astimezone(tz).dst() != timedelta(0)
def WQ_DST_handler(TZ, **kwargs):
if is_DST(TZ):
print('Currently is daily saving time (DST) in {0}, will process to next task now'.format(TZ))
else:
print('Currently is not daily saving time (DST) in {0}, will sleep 1 hour...'.format(TZ))
time.sleep(60 * 60)
DST_handler = PythonOperator(
task_id='DST_handler',
python_callable=WQ_DST_handler,
op_kwargs={'TZ': TZ_of_dag},
dag=dag
)
DST_handler >> main_tasks
这种解决方法有一个缺点:对于需要在DST TZ中运行的任何DAG,我们必须创建另外一个任务(上例中的DST_handler),并且此任务仍然需要发送到工作节点以执行(尽管它几乎只是一个睡眠命令。)
答案 3 :(得分:1)
当气流在1.8.x版上时被问到这个问题。
此功能自气流1.10起已内置。
https://airflow.apache.org/timezone.html
在airflow.cfg
中设置时区,应该正确处理dst。