【发布时间】:2018-07-26 21:50:09
【问题描述】:
有没有办法从 yaml 文件中指定的字典创建动态表?我在 yaml 文件中定义了很多 ETL 配置,所以我很好奇我是否也可以向其中添加表创建方面,这样我就不必在单独的目录中修改单独的 .sql 文件。
database:
table: 'schema.fact_stuff'
create_columns: [
{}
] #not sure how this section should be
我在 stackoverflow 上找到了一个解决方案,该解决方案将一些列表压缩在一起,这是类似的,但我更愿意明确定义每一列。
{'column_name': 'id', 'column_type': Integer, 'primary_key': False, 'nullable': True}
我最终让它与这个一起工作:
from sqlalchemy.types import (Integer, NUMERIC, TEXT, BOOLEAN, TIMESTAMP, DATE)
sql_types = {'integer': Integer,
'numeric': NUMERIC,
'text': TEXT,
'date': DATE,
'timestamp': TIMESTAMP(timezone=False),
'timestamptz': TIMESTAMP(timezone=True)}
exclude_list = ['original_name']
table_dict = [{k: v for k, v in d.items() if k not in exclude_list} for d in c[variable]['load']['columns']]
for column in table_dict:
for key, val in column.copy().items():
if key == 'type_':
column[key] = sql_types[val]
elif key == 'default':
column[key] = dt.datetime.utcnow
metadata = sa.MetaData(schema=c[variable]['load']['schema'])
metadata.reflect(bind=engine, autoload=True)
fact = sa.Table(c[variable]['load']['table'], metadata, extend_existing=True,
*(sa.Column(**kwargs) for kwargs in table_dict))
fact.create_all(engine, checkfirst=True)
但后来我转而让 pandas 确定 dtypes,而不是在 yaml 文件中定义它们。这将使用 jinja2 模板创建 sql,然后我遍历所有数据源以创建 DDL。
def pandas_to_postgres(df):
dtype_dict = {
'i': 'integer',
'O': 'text',
'f': 'real',
'b': 'boolean',
'datetime64[ns]': 'timestamp',
'datetime64[ns, UTC]': 'timestampz',
}
column_list = []
column_dict = {}
for k, v in df.dtypes.items():
column_dict['name'] = k
column_dict['dtype'] = dtype_dict.get(v.kind, 'text')
column_list.append(column_dict.copy())
return column_list
def generate_create_table(df, schema, table, table_type, columns, constraint, unique_columns):
""" Returns a dictionary of coefs from training """
query = Template(
template
).render(
schema_name=schema,
table_name=table,
table_type=table_type,
columns=columns,
constraint=constraint,
constraint_columns=unique_columns
)
print(query)
【问题讨论】:
标签: python sqlalchemy yaml