在ETL过程中,我需要从一个Postgres数据库提取一个JSON列并将其加载到另一个数据库。我们使用Pandas来实现这一点,因为它有很多方法可以从不同的源/目标读取和写入数据,并且所有的转换都可以使用Python和Pandas编写。坦率地说,我们对这种方法非常满意。但我们遇到了一个问题。
通常,读写数据非常容易。您只需使用pandas.read_sql_table从源读取数据,并使用pandas.to_sql将数据写入目标。但是,由于其中一个源表有一个JSON类型的列(来自Postgres),因此to_sql函数崩溃,并显示以下错误消息。
df.to_sql(table_name, analytics_db)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/pandas/core/generic.py", line 1201, in to_sql
chunksize=chunksize, dtype=dtype)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/pandas/io/sql.py", line 470, in to_sql
chunksize=chunksize, dtype=dtype)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/pandas/io/sql.py", line 1147, in to_sql
table.insert(chunksize)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/pandas/io/sql.py", line 663, in insert
self._execute_insert(conn, keys, chunk_iter)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/pandas/io/sql.py", line 638, in _execute_insert
conn.execute(self.insert_statement(), data)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/engine/base.py", line 945, in execute
return meth(self, multiparams, params)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/sql/elements.py", line 263, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement
compiled_sql, distilled_params
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/engine/base.py", line 1189, in _execute_context
context)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/engine/base.py", line 1393, in _handle_dbapi_exception
exc_info
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/util/compat.py", line 202, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/engine/base.py", line 1159, in _execute_context
context)
File "/home/ec2-user/python-virtual-environments/etl/local/lib64/python2.7/site-packages/sqlalchemy/engine/default.py", line 459, in do_executemany
cursor.executemany(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'dict'发布于 2017-01-05 01:03:29
我一直在网上搜索解决方案,但没有找到任何解决方案,所以我们想出了(可能有更好的方法,但如果其他人遇到这种情况,至少这是一个开始)。
在to_sql中指定dtype参数。
我们从:df.to_sql(table_name, analytics_db)转到了df.to_sql(table_name, analytics_db, dtype={'name_of_json_column_in_source_table': sqlalchemy.types.JSON}),它很好用。
发布于 2018-06-13 04:03:00
如果使用json.dumps() (重新)创建JSON列,那么一切都准备好了。这样,不仅可以使用pandas的.to_sql()方法写入数据,还可以使用速度更快的PostgreSQL的COPY方法(通过copy_expert() of psycopg2或sqlalchemy的raw_connection())。
为简单起见,我们假设有一列字典应该写入JSON(B)列:
import json
import pandas as pd
df = pd.DataFrame([['row1',{'a':1, 'b':2}],
['row2',{'a':3,'b':4,'c':'some text'}]],
columns=['r','kv'])
# conversion function:
def dict2json(dictionary):
return json.dumps(dictionary, ensure_ascii=False)
# overwrite the dict column with json-strings
df['kv'] = df.kv.map(dict2json)发布于 2021-01-26 23:11:58
我无法评论peralmq's answer,但在postgresql JSONB的情况下,您可以使用
from sqlalchemy import dialects
dataframe.to_sql(..., dtype={"json_column":dialects.postgresql.JSONB})https://stackoverflow.com/questions/41469430
复制相似问题