我有一个Airflow脚本,可以将table_2中的数据插入到table_1中。作为气流初始化过程的一部分,我看到即使我没有触发或计划,插入功能仍在后台运行。我想知道脚本中有什么错误使它自动触发。我需要在下面的脚本中修改什么,以确保它不会在初始化过程中执行命令。
## Library Imports
import psycopg2
import airflow
from airflow import DAG
from airflow.operators import BashOperator
from sqlalchemy import create_engine
import io
# Following are defaults which can be overridden later on
default_args = {
'owner': 'admin',
'depends_on_past': False,
'start_date': datetime(2018, 5, 25),
'email': ['admin@mail.com'],
'email_on_failure': True,
'email_on_retry': True,
'retries': 1,
'retry_delay': timedelta(minutes=1),
}
dag = DAG('sample', default_args=default_args)
#######################
def db_login():
global db_con
try:
db_con = psycopg2.connect(" dbname = 'db' user = 'user' password = 'pass' host = 'hostname' port = '5439' sslmode = 'require' ")
except:
print("I am unable to connect to the database.")
print('Connection Task Complete: Connected to DB')
return(db_con)
#######################
def insert_data():
cur = db_con.cursor()
cur.execute("""insert into table_1 select id,name,status from table_2 limit 2 ;""")
db_con.commit()
print('ETL Task Complete: Inserting data into table_1')
db_login()
insert_data()
db_con.close()
##########################################
t1 = BashOperator(
task_id='db_con',
python_callable=db_login(),
bash_command='python3 ~/airflow/dags/sample.py',
email_on_failure=True,
email=['admin@mail.com'],
dag=dag)
t2 = BashOperator(
task_id='insert',
python_callable=insert_data(),
bash_command='python3 ~/airflow/dags/sample.py',
email_on_failure=True,
email=['admin@mail.com'],
dag=dag)
t1.set_downstream(t2)
任何人都可以为此提供帮助。感谢。
更新代码:
## Third party Library Imports
import psycopg2
import airflow
from airflow import DAG
from airflow.operators import BashOperator
from datetime import datetime, timedelta
from sqlalchemy import create_engine
import io
default_args = {
'owner': 'admin',
#'depends_on_past': False,
'start_date': datetime(2018, 5, 25),
'email': ['admin@mail.com'],
'email_on_failure': True,
'email_on_retry': True,
'retries': 1,
'retry_delay': timedelta(minutes=1), }
dag = DAG('sample', default_args=default_args, catchup=False, schedule_interval="@once")
def db_login():
global db_con
try:
db_con = psycopg2.connect(
" dbname = 'db' user = 'user' password = 'password' host = 'host' port = '5439' sslmode = 'require' ")
except:
print("I am unable to connect to the database.")
print('Connection success')
return (db_con)
def insert_data():
cur = db_con.cursor()
cur.execute("""insert into table_1 select id,name,status from table_2 limit 2;""")
db_con.commit()
print('ETL Task Complete: Inserting data into table_1')
def load_etl():
db_login()
insert_data()
dwh_connection.close()
#Function to execute the query
load_etl()
t1 = BashOperator(
task_id='db_connection',
python_callable=load_etl(),
bash_command='python3 ~/airflow/dags/sample.py',
email_on_failure=True,
email=['admin@mail.com'],
dag=dag)
#t2 = BashOperator(
#task_id='ops_load_del',
#python_callable=insert_data(),
#bash_command='python3 ~/airflow/dags/sample.py',
#email_on_failure=True,
#email=['admin@mail.com'],
#dag=dag)
t1
#t1.set_downstream(t2)
答案 0 :(得分:1)
如果从Python式的角度来看你的DAG,那么缩进就会激起一些想法。
首先,尝试使用python name-of-dag.py
执行DAG。是的,不要使用airflow
命令。 Airflow的某些部分也在进行此操作,以检查要做什么。
现在,如果正在执行某些代码,则可能会将其连接到该意图。
功能分析
这里的缩进似乎破了:
def db_login(): 全局db_con 尝试: db_con = psycopg2.connect(" dbname =' db' user =' user' password =' pass' host =' hostname' port =' 5439' sslmode ='要求'") 除了: 打印("我无法连接到数据库。") 打印('连接任务完成:连接到DB') 返回(db_con)
应该是:
def db_login():
global db_con
try:
db_con = psycopg2.connect(" dbname = 'db' user = 'user' password = 'pass' host = 'hostname' port = '5439' sslmode = 'require' ")
except:
print("I am unable to connect to the database.")
print('Connection Task Complete: Connected to DB')
return(db_con)
否则将始终执行最左侧的代码。
另外:全局变量不会在Airflow的其他方法中可用!要共享连接,请使用例如气流XCOM
:https://airflow.apache.org/concepts.html#xcoms
直接在DAG中调用函数
另外,由于某些原因我不知道,你想要完全在Airflow 的控制范围之外执行某些函数,但每次执行时都要执行。
db_login()
insert_data()
db_con.close()
此代码将在每次调用DAG时执行 (可能很多),并且可能与您想要的日程安排完全不同。
如果您希望此代码用于测试目的,您可能希望将其置于主调用中:
if __name__ == '__main__':
db_login()
insert_data()
db_con.close()
即使您这样做 - 关闭操作仅在此工作流程中可用,但在DAG中不可用。没有任务可以关闭连接。
由于您正在使用PythonOperator
,因此构建一个小的def来执行此操作并且只有一个调用此def的任务也是明智的:
def load_etl():
db_login()
insert_data()
db_con.close()
<强> TL / DR 强> 消除所有缩进错误,这样如果您纯粹使用Python调用该文件,则不会执行任何代码。
修改强>
这也意味着任何函数调用都不在任务或def之外。这一行
#Function to execute the query
load_etl()
将被执行,因为它不是任务或def的一部分。它必须被删除。然后它应该工作,因为函数调用是任务的一部分。
由于此函数是Python函数,因此您应该使用PythonOperator
及其参数python_callable=load_etl
(注意:行尾没有括号)