web-dev-qa-db-fra.com

copier les données de csv vers postgresql en utilisant python

Je suis sur Windows 7 64 bits . J'ai un fichier csv 'data.csv' . Je veux importer des données dans une table postgresql 'temp_unicommerce_status' via un script python.

Mon script est:

import psycopg2
conn = psycopg2.connect("Host='localhost' port='5432' dbname='Ekodev' user='bn_openerp' password='fa05844d'")
cur = conn.cursor()
cur.execute("""truncate table "meta".temp_unicommerce_status;""")
cur.execute("""Copy temp_unicommerce_status from 'C:\Users\n\Desktop\data.csv';""")
conn.commit()
conn.close()

Je reçois cette erreur

Traceback (most recent call last):
  File "C:\Users\n\Documents\NetBeansProjects\Unicommerce_Status_Update\src\unicommerce_status_update.py", line 5, in <module>
cur.execute("""Copy temp_unicommerce_status from     'C:\\Users\\n\\Desktop\\data.csv';""")
psycopg2.ProgrammingError: must be superuser to COPY to or from a file
HINT:  Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.
10
Manish Gupta

Utilisez la méthode du curseur copy_from

f = open(r'C:\Users\n\Desktop\data.csv', 'r')
cur.copy_from(f, temp_unicommerce_status, sep=',')
f.close()

Le fichier doit être passé en tant qu'objet.

Puisque vous copiez depuis un fichier csv, il est nécessaire de spécifier le séparateur car le caractère par défaut est un caractère de tabulation

19
Clodoaldo Neto

La façon dont j'ai résolu ce problème, en particulier d'utiliser la fonction copy_expert de la classe de curseurs psychopg2 (Docs: http://initd.org/psycopg/docs/cursor.html ). copy_expert vous permet d'utiliser STDIN, évitant ainsi la nécessité d'émettre un privilège de superutilisateur pour l'utilisateur postgres. Votre accès au fichier dépend alors de l'accès de l'utilisateur client (linux/windows/mac) au fichier.

Depuis Postgres COPY Docs ( https://www.postgresql.org/docs/current/static/sql-copy.html ):

Ne confondez pas COPY avec l'instruction psql\copy.\copy appelle COPY FROM STDIN ou COPY TO STDOUT, puis extrait/stocke les données dans un fichier accessible au client psql. Ainsi, l'accessibilité au fichier et les droits d'accès dépendent du client plutôt que du serveur lorsque\copy est utilisé.

Vous pouvez également laisser les autorisations définies strictement pour l'accès au dossier personnel de development_user et au dossier de l'application.

csv_file_name = '/home/user/some_file.csv'
sql = "COPY table_name FROM STDIN DELIMITER '|' CSV HEADER"
cursor.copy_expert(sql, open(csv_file_name, "r"))
3
rippledj

Voici un extrait de la documentation PostgreSQL pertinente: COPY avec un nom de fichier indique au serveur PostgreSQL de lire ou d’écrire directement dans un fichier. Le fichier doit être accessible au serveur et le nom doit être spécifié du point de vue du serveur. Lorsque STDIN ou STDOUT est spécifié, les données sont transmises via la connexion entre le client et le serveur.

C'est la raison pour laquelle la commande copy vers ou depuis un fichier est restreinte à un superutilisateur PostgreSQL: le fichier doit être présent sur le serveur et chargé directement par le processus serveur.

Vous devriez plutôt utiliser:

cur.copy_from(r'C:\Users\n\Desktop\data.csv', temp_unicommerce_status)

comme suggéré par cette autre réponse , car en interne, il utilise COPY à partir de stdin.

1
Serge Ballesta

Je sais que cette question a reçu une réponse, mais voici mes deux centimes. J'ajoute un peu plus de description:

Vous pouvez utiliser la méthode cursor.copy_from:

Vous devez d’abord créer une table avec le même nombre de colonnes que votre fichier csv.

Exemple:

Mon csv ressemble à ceci:

Name,       age , college , id_no , country , state   , phone_no

demo_name   22  , bdsu    , 1456  , demo_co , demo_da , 9894321_

Créez d'abord une table:

import psycopg2
from psycopg2 import Error

connection = psycopg2.connect(user = "demo_user",
                                  password = "demo_pass",
                                  Host = "127.0.0.1",
                                  port = "5432",
                                  database = "postgres")
cursor = connection.cursor()


create_table_query = '''CREATE TABLE data_set
(Name  TEXT NOT NULL ,
age  TEXT NOT NULL ,
college  TEXT NOT NULL ,
id_no TEXT NOT NULL ,
country TEXT NOT NULL ,
state TEXT NOT NULL ,
phone_no TEXT NOT NULL);'''

cursor.execute(create_table_query)
connection.commit()

Maintenant, vous pouvez simplement utiliser cursor.copy_from où vous avez besoin de trois paramètres:

first file object , second table_name , third sep type

vous pouvez copier maintenant:

f = open(r'final_data.csv', 'r')
cursor.copy_from(f, 'data_set', sep=',')
f.close()

terminé

0
Aaditya Ura

Vous pouvez utiliser d6tstack pour simplifier cela.

import d6tstack
import glob

c = d6tstack.combine_csv.CombinerCSV([r'C:\Users\n\Desktop\data.csv']) # single-file
c = d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv')) # multi-file
c.to_psql_combine('postgresql+psycopg2://psqlusr:psqlpwdpsqlpwd@localhost/psqltest', 'tablename')

Il traite également des modifications de schéma data , crée/ajoute/remplace une table et vous permet de prétraiter les données avec des pandas.

0
citynorman