Importer des catalogues csv dans une base de données

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour, j’ai un petit souci et je ne vois pas comment m’en dépatouiller. Je n’ai pas trouvé (ou mal cherché) sur mon moteur de recherche préféré.

J’ai plusieurs "Catalogues" à insérer dans une base de données. Les tables contenant ces "Catalogues" comportent 3 champs pour la plupart (id, Code, Libellé), mais j’ai un catalogue qui contient 4 champs.

Le but de mon script est d’avoir une fonction qui fonctionne pour toutes mes insertions. J’ai donc bricolé un peu. Voici une extraction du code posant souci:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def mafonction(nom_fichier, table, champs, libelle_nb_valeurs):
  with open(nom_fichier, newline='') as fichier:
      lecteur = csv.reader(fichier, delimiter=';', quotechar='|')
      for row in lecteur:
          Code = str(row[0])
          Libelle = str(row[1])

          if Code != "Code":
              valeurs = [Code, Libelle]
              curseur.execute("""INSERT INTO """ + table + """(""" + champs + """) VALUES |(""" + libelle_nb_valeurs + """)""", (valeurs));


nom_fichier = "Catalogue_Modulateur.csv"
table = "CATALOGUE_MODULATEUR"
champs = "CATALOGUE_MODULATEUR_Code, CATALOGUE_MODULATEUR_Libelle"
libelle_nb_valeurs = "?, ?" # Mettre autant de "?" qu'il y a de données à insérer

mafonction(nom_fichier, table, champs, libelle_nb_valeurs)

J’ai été obligé de garder cette partie là :

1
2
Code = str(row[0])
Libelle = str(row[1])

Du coup, je traite bien le cas où j’ai deux champs (hors identifiant) mais pas celui où j’en ai un de plus.

Je pourrais ajouter une variable et faire :

1
mafonction(nom_fichier, nb_champs, table, champs, libelle_nb_valeurs)

Puis dans ma fonction dire que si nb_champs = 3 j’ai :

1
2
Code = str(row[0])
Libelle = str(row[1])

Et si j’ai 4 champs, j’ai :

1
2
3
Code = str(row[0])
Libelle = str(row[1])
xxx = str(row[2])

Mais c’est pas super … Surtout que je pourrais éventuellement vouloir intégrer dans ma bdd des fichiers csv avec plus de champs dans le futur.

Une idée ? Merci d’avance.

Dans le doute, reboot.

+0 -0

Cette réponse a aidé l’auteur du sujet

Salut,

Je pense que si j’avais à faire la même chose, je l’aurais fait assez différemment, pour avoir un code plus clair (une section qui lit le CSV et une section qui ajoute les données à la base de données) et pour tirer parti du fait qu’on peut insert plusieurs lignes en une requête (doc). Par contre, il ne faut pas que le fichier CSV dépasse les quelques gigaoctets, pour pouvoir le stocker en mémoire.

J’aurai utilisé une liste par type de données que tu peux avoir, en utilisant des tuples ou mieux, des collections.namedtuple (doc). On boucle sur les données et on ajoute à la bonne liste (en regardant row[0] pour le type et ajoutant row[1:] dans un namedtuple dans la bonne liste (avec Foo(*row[1:])).
Ensuite, tu génères une requête par type de données et tu y mets tout les éléments de la liste qui correspond (il faudrait peut-être découper si il y a beaucoup d’éléments).

Si il y a trop de données et donc qui ne peuvent pas toutes être stockés en RAM, il faudrait lire chaque entrée, ajouter à la liste qui correspond et faire une requête pour ajouter les éléments à la BDD quand une liste devient trop grosse (puis la vider et continuer).

Auteur du sujet

Pourquoi ne pas prendre directement l’injecteur de Sqlite, à la place de refaire une roue carrée ?

https://www.sqlite.org/cvstrac/wiki?p=ImportingFiles

bacelar

Ah oui pas mal, étant donné que quelques lignes plus haut dans le script, j’importe des csv que je traite et que j’inscris en bdd, j’ai pas cherché plus loin mais effectivement ça me semble pas mal.

Salut,

Je pense que si j’avais à faire la même chose, je l’aurais fait assez différemment, pour avoir un code plus clair (une section qui lit le CSV et une section qui ajoute les données à la base de données) et pour tirer parti du fait qu’on peut insert plusieurs lignes en une requête (doc). Par contre, il ne faut pas que le fichier CSV dépasse les quelques gigaoctets, pour pouvoir le stocker en mémoire.

J’aurai utilisé une liste par type de données que tu peux avoir, en utilisant des tuples ou mieux, des collections.namedtuple (doc). On boucle sur les données et on ajoute à la bonne liste (en regardant row[0] pour le type et ajoutant row[1:] dans un namedtuple dans la bonne liste (avec Foo(*row[1:])).
Ensuite, tu génères une requête par type de données et tu y mets tout les éléments de la liste qui correspond (il faudrait peut-être découper si il y a beaucoup d’éléments).

Si il y a trop de données et donc qui ne peuvent pas toutes être stockés en RAM, il faudrait lire chaque entrée, ajouter à la liste qui correspond et faire une requête pour ajouter les éléments à la BDD quand une liste devient trop grosse (puis la vider et continuer).

tleb

Je vais jeter un œil à tout ça merci.

Édité par Aurel_B_

Dans le doute, reboot.

+0 -0
Auteur du sujet

Merci à vous deux j’ai bricolé un peu et ça marche. Il faut que je jette un œil pour faire un multi insert c’est pas mal comme idée.

Je mets de côté l’injecteur SQLite pour plus tard. Il vaut que je peaufine tout ça pour optimiser un peu le truc.

Encore merci.

Dans le doute, reboot.

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte