postgresql - transcript_grades - psycopg2 programmingerror permission denied for relation ir_module_module
SQLAlchemy, Psycopg2 y Postgresql COPY (6)
La respuesta aceptada es correcta, pero si desea más que solo el comentario de EoghanM para continuar con el siguiente trabajo, le ayudé a COPIAR una tabla a CSV ...
from sqlalchemy import sessionmaker, create_engine
eng = create_engine("postgresql://user:pwd@host:5432/db")
ses = sessionmaker(bind=engine)
dbcopy_f = open(''/tmp/some_table_copy.csv'',''wb'')
copy_sql = ''COPY some_table TO STDOUT WITH CSV HEADER''
fake_conn = eng.raw_connection()
fake_cur = fake_conn.cursor()
fake_cur.copy_expert(copy_sql, dbcopy_f)
El sessionmaker
no es necesario, pero si tiene la costumbre de crear el motor y la sesión al mismo tiempo para usar raw_connection
, necesitará separarlos (a menos que haya alguna forma de acceder al motor a través del objeto de sesión que yo no se) La cadena sql proporcionada a copy_expert
tampoco es la única forma de hacerlo, hay una función copy_to
básica que puede usar con un subconjunto de los parámetros que podría pasar a una consulta COPY
TO normal. El rendimiento general del comando me parece rápido, copiando una tabla de ~ 20000 filas.
http://initd.org/psycopg/docs/cursor.html#cursor.copy_to http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.Engine.raw_connection
Parece que Psycopg tiene un comando personalizado para ejecutar una COPY :
psycopg2 COPY usando cursor.copy_from () se congela con entradas grandes
¿Hay alguna forma de acceder a esta funcionalidad desde SQLAlchemy?
No es necesario desplegar a psycopg2, use raw_connection ni un cursor.
Simplemente ejecute el sql como de costumbre, incluso puede usar parámetros de enlace con text()
:
engine.execute(text(''''''copy some_table from :csv
delimiter '','' csv''''''
).execution_options(autocommit=True),
csv=''/tmp/a.csv'')
Puede eliminar las execution_options(autocommit=True)
si este PR será aceptado
Puedes usar:
def to_sql(engine, df, table, if_exists=''fail'', sep=''/t'', encoding=''utf8''):
# Create Table
df[:0].to_sql(table, engine, if_exists=if_exists)
# Prepare data
output = cStringIO.StringIO()
df.to_csv(output, sep=sep, header=False, encoding=encoding)
output.seek(0)
# Insert data
connection = engine.raw_connection()
cursor = connection.cursor()
cursor.copy_from(output, table, sep=sep, null='''')
connection.commit()
cursor.close()
Inserto 200000 líneas en 5 segundos en lugar de 4 minutos
Si puede llegar al motor, tiene todo lo que necesita para hacer esto:
engine = create_engine(''postgresql+psycopg2://myuser:password@localhost/mydb'')
# or
engine = session.engine
# or any other way you know to get to the engine
Ahora puedes trabajar.
# isolate a connection
connection = engine.connect().connection
# get the cursor
cursor = connection.cursor()
Aquí hay algunas plantillas para la instrucción COPY para usar con cursor.copy_expert()
, una opción más completa y flexible que copy_from()
o copy_to()
como se indica aquí: http://initd.org/psycopg/docs/cursor.html#cursor.copy_expert .
# to dump to a file
dump_to = """
COPY mytable
TO STDOUT
WITH (
FORMAT CSV,
DELIMITER '','',
HEADER
);
"""
# to copy from a file:
copy_from = """
COPY mytable
FROM STDIN
WITH (
FORMAT CSV,
DELIMITER '','',
HEADER
);
"""
Compruebe qué significan las opciones anteriores y otras que pueden ser de interés para su situación específica https://www.postgresql.org/docs/current/static/sql-copy.html .
NOTA IMPORTANTE: el enlace a la documentación de cursor.copy_expert()
indica el uso de STDOUT para escribir en un archivo y STDIN para copiar de un archivo. Pero si observa la sintaxis en el manual de PostgreSQL, notará que también puede especificar el archivo para escribir en o desde directamente en la declaración COPY. No hagas eso, es probable que solo pierdas el tiempo si no estás ejecutando como root (¿quién ejecuta Python como root durante el desarrollo?) Simplemente haz lo que está indicado en los documentos de psycopg2 y especifica STDIN o STDOUT en tu declaración con el cursor.copy_expert()
, debería estar bien.
# running the copy statement
with open(''/path/to/your/data/file.csv'') as f:
cursor.copy_expert(copy_from, file=f)
# don''t forget to commit the changes.
connection.commit()
Si su motor está configurado con una cadena de conexión psycopg2 (que es la opción predeterminada, por lo tanto, "postgresql://..."
o "postgresql+psycopg2://..."
), puede crear un cursor psycopg2 desde un SQL Sesión de alquimia utilizando
cursor = session.connection().connection.cursor()
que puedes usar para ejecutar
cursor.copy_from(...)
El cursor estará activo en la misma transacción que su sesión actual. Si se produce una commit
o una rollback
, cualquier uso adicional del cursor con el lanzamiento de un psycopg2.InterfaceError
, tendría que crear uno nuevo.
Es posible que tenga que usar solo psycopg2 para exponer esta funcionalidad y renunciar a las capacidades de ORM. Supongo que realmente no veo el beneficio de ORM en una operación de este tipo ya que es un inserto a granel recto y tratar con objetos individuales a la vez que un ORM no tendría mucho sentido.