Antworten:
Ab pandas 0.14 (veröffentlicht Ende Mai 2014) wird postgresql unterstützt. Das sql
Modul unterstützt jetzt sqlalchemy
verschiedene Datenbankvarianten. Sie können eine SQLalchemy-Engine für eine PostgresQL-Datenbank übergeben (siehe Dokumente ). Z.B:
from sqlalchemy import create_engine
engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase')
df.to_sql('table_name', engine)
Sie haben Recht, dass in Pandas bis Version 0.13.1 postgresql nicht unterstützt wurde. Wenn Sie eine ältere Version von Pandas verwenden müssen, finden Sie hier eine gepatchte Version von pandas.io.sql
: https://gist.github.com/jorisvandenbossche/10841234 .
Ich habe dies vor einiger Zeit geschrieben, kann also nicht vollständig garantieren, dass es immer funktioniert, aber die Basis sollte da sein. Wenn Sie diese Datei in Ihr Arbeitsverzeichnis con
einfügen und importieren, sollten Sie in der Lage sein (wo ist eine Postgresql-Verbindung):
import sql # the patched version (file is named sql.py)
sql.write_frame(df, 'table_name', con, flavor='postgresql')
Sqlalchemy engine
Kann ich eine neue Postgres
Verbindung verwenden, die mit erstellt wurde, anstatt eine neue zu erstellen psycopg2.connect()
?
Schnellere Option:
Mit dem folgenden Code wird Ihr Pandas DF viel schneller als mit der Methode df.to_sql in die Postgres-Datenbank kopiert, und Sie benötigen keine Zwischen-CSV-Datei, um die df zu speichern.
Erstellen Sie eine Engine basierend auf Ihren DB-Spezifikationen.
Erstellen Sie in Ihrer Postgres-Datenbank eine Tabelle mit der gleichen Anzahl von Spalten wie der Datenrahmen (df).
Daten in DF werden in Ihre Postgres-Tabelle eingefügt .
from sqlalchemy import create_engine
import psycopg2
import io
Wenn Sie die Tabelle ersetzen möchten, können wir sie durch die normale to_sql-Methode ersetzen, indem wir Header aus unserem df verwenden und dann den gesamten zeitaufwändigen df in die DB laden.
engine = create_engine('postgresql+psycopg2://username:password@host:port/database')
df.head(0).to_sql('table_name', engine, if_exists='replace',index=False) #truncates the table
conn = engine.raw_connection()
cur = conn.cursor()
output = io.StringIO()
df.to_csv(output, sep='\t', header=False, index=False)
output.seek(0)
contents = output.getvalue()
cur.copy_from(output, 'table_name', null="") # null values become ''
conn.commit()
contents
? Sollte dies derjenige sein, in dem geschrieben steht copy_from()
?
contents
Variable, alles andere sollte gut funktionieren
output.seek(0)
?
Pandas 0.24.0+ Lösung
In Pandas 0.24.0 wurde eine neue Funktion eingeführt, die speziell für schnelles Schreiben in Postgres entwickelt wurde. Weitere Informationen finden Sie hier: https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html#io-sql-method
import csv
from io import StringIO
from sqlalchemy import create_engine
def psql_insert_copy(table, conn, keys, data_iter):
# gets a DBAPI connection that can provide a cursor
dbapi_conn = conn.connection
with dbapi_conn.cursor() as cur:
s_buf = StringIO()
writer = csv.writer(s_buf)
writer.writerows(data_iter)
s_buf.seek(0)
columns = ', '.join('"{}"'.format(k) for k in keys)
if table.schema:
table_name = '{}.{}'.format(table.schema, table.name)
else:
table_name = table.name
sql = 'COPY {} ({}) FROM STDIN WITH CSV'.format(
table_name, columns)
cur.copy_expert(sql=sql, file=s_buf)
engine = create_engine('postgresql://myusername:mypassword@myhost:5432/mydatabase')
df.to_sql('table_name', engine, method=psql_insert_copy)
method='multi'
Option zum Hinzufügen schnell genug. Aber ja, diese COPY
Methode ist momentan der schnellste.
with
schreibt in einen In-Memory-Puffer. Der letzte Teil von with
besteht darin, eine SQL-Anweisung zu verwenden und die Geschwindigkeit von copy_expert zu nutzen, um die Daten in großen Mengen zu laden. Was ist der mittlere Teil, der damit beginnt columns =
?
keys
Argumente in der psql_insert_copy
Funktion erklären ? Wie bekommt es irgendwelche Schlüssel und sind die Schlüssel nur die Spaltennamen?
Table 'XYZ' already exists
. Soweit ich weiß, sollte es keine Tabelle erstellen, oder?
df.to_sql('table_name', engine, if_exists='replace', method=psql_insert_copy)
- dies erstellt eine Tabelle in Ihrer Datenbank.
So habe ich es gemacht.
Es kann schneller sein, weil es verwendet execute_batch
:
# df is the dataframe
if len(df) > 0:
df_columns = list(df)
# create (col1,col2,...)
columns = ",".join(df_columns)
# create VALUES('%s', '%s",...) one '%s' per column
values = "VALUES({})".format(",".join(["%s" for _ in df_columns]))
#create INSERT INTO table (columns) VALUES('%s',...)
insert_stmt = "INSERT INTO {} ({}) {}".format(table,columns,values)
cur = conn.cursor()
psycopg2.extras.execute_batch(cur, insert_stmt, df.values)
conn.commit()
cur.close()
Für Python 2.7 und Pandas 0.24.2 und mit Psycopg2
Psycopg2-Verbindungsmodul
def dbConnect (db_parm, username_parm, host_parm, pw_parm):
# Parse in connection information
credentials = {'host': host_parm, 'database': db_parm, 'user': username_parm, 'password': pw_parm}
conn = psycopg2.connect(**credentials)
conn.autocommit = True # auto-commit each entry to the database
conn.cursor_factory = RealDictCursor
cur = conn.cursor()
print ("Connected Successfully to DB: " + str(db_parm) + "@" + str(host_parm))
return conn, cur
Stellen Sie eine Verbindung zur Datenbank her
conn, cur = dbConnect(databaseName, dbUser, dbHost, dbPwd)
Angenommen, der Datenrahmen ist bereits als df vorhanden
output = io.BytesIO() # For Python3 use StringIO
df.to_csv(output, sep='\t', header=True, index=False)
output.seek(0) # Required for rewinding the String object
copy_query = "COPY mem_info FROM STDOUT csv DELIMITER '\t' NULL '' ESCAPE '\\' HEADER " # Replace your table name in place of mem_info
cur.copy_expert(copy_query, output)
conn.commit()