2

I want to write a pandas dataframe to a postgres table. I make a connection to db as follows:

import psycopg2
import pandas as pd
import sqlalchemy

def connect(user, password, db, host='localhost', port=5432):
    '''Returns a connection and a metadata object'''
    url  = 'postgresql://{}:{}@{}:{}/{}'
    url = url.format(user, password, host, port, db)

    # The return value of create_engine() is our connection object
    con = sqlalchemy.create_engine(url, client_encoding='utf8')

    # We then bind the connection to MetaData()
    meta = sqlalchemy.MetaData(bind=con, reflect=True)

    return con, meta

con, meta = connect('user_name', 'password', 'db_name', host='host_name')

When I read from a table that is already populated, it works fine:

df = pd.read_sql("SELECT * FROM db.table_name limit 10",con=con)
print df

I would like to be able to write df to a table. To test this, I have a temporary table called 'test' with two fields name and age.

# create a temp df
table = [['name', 'age'], ['nameA' , 20], ['nameB', 30]]
headers = table.pop(0)
df = pd.DataFrame(table, columns=headers)
# write to db
df.to_sql('db.test', con, if_exists = 'replace', index=False)

I then check if the temp table is populated:

df = pd.read_sql("SELECT * FROM db.test limit 10",con=con)
print df

I get an empty dataframe! I got no errors when I use df.to_sql but nothing is getting written to the database (?). What am I missing and how do I go about fixing this?

Versions:

Pandas: 0.19.2
Sqlachemy: 1.1.10
Postgres: 9.4.9
6
  • 1
    Try not using period in table name. Commented May 30, 2017 at 22:12
  • @Parfait, can you please elaborate what you mean by that? Did you mean at the db.test? It is to point to the table called test under db schema. Commented May 30, 2017 at 22:37
  • 1
    But you connect to the db schema in connection engine. It is redundant and maybe affecting the table creation. Just reference test. Commented May 30, 2017 at 23:08
  • @Parfait tried that -- gives me an error about not finding test, does not complain if I do db.test. Commented May 30, 2017 at 23:55
  • 1
    Do note: you can answer your own question especially to help future readers. Be sure to include the full solution with an explanation of what worked. Commented May 31, 2017 at 1:38

1 Answer 1

3

I have not figured out why df.to_sql did not write to the table. Writing to table using pd.io.sql.SQLDatabase worked for my test case:

meta = sqlalchemy.MetaData(con, schema='db_name')
meta.reflect()
pdsql = pd.io.sql.SQLDatabase(con, meta=meta)
pdsql.to_sql(df, 'test', if_exists='replace')

I would not consider this THE solution -- I'd be happy to accept better solution or an answer that brings a closure to why df.to_sql() does not behave as expected.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.