Script de vérification de format CSV

Fermé
lynow Messages postés 22 Date d'inscription jeudi 18 mars 2021 Statut Membre Dernière intervention 28 juin 2023 - 10 janv. 2023 à 10:40
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 - 13 janv. 2023 à 15:26

Bonjour,

Je vais débuter un script qui va permettre de vérifier si un fichier CSV est au format voulu ou non.

Pour comprendre, prenons l'exemple des deux premières colonnes qui donnent un type et une valeur.

Le script devra vérifier si les valeurs données en colonne 1 correspondent bien aux valeurs données en colonne 2. En effet, je veux éviter les incohérences. De plus, il faut que les informations données en type existent dans ma base de donnée. Je dois donc vérifier si le type existe et si la valeur et le type sont bien cohérents. Le problème est que j'ai environ 200 types possibles, je ne peux donc pas, via par exemple un regex, regarder le type et voir le regex pour la valeur correspond bien à la valeur donnée.

Je viens donc vers vous pour savoir par quel biais je dois partir, au niveau python. Par exemple, je n'ai jamais utilisé d'objets sur python. Dans ce cas là, dois-je les utiliser ? Ensuite, j'ai pensé à créer un grand tableau avec les types et valeurs regex possibles, ainsi je pourrais le parcourir pour vérifier les cohérences ou non. Peut-être que quelqu'un aura une idée que je n'aurais pas pensé.

Les autres vérifications sont plus simples : minuscules pour les types, supprimer les valeurs en doublon, format pour les dates, etc.

Lynow.

A voir également:

4 réponses

Whismeril Messages postés 19039 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 mai 2024 932
10 janv. 2023 à 13:37

Bonjour 

si par exemple le type "rouge" en colonne 1 est  cohérent de "Cerise", "Fraise" et "Groseille" en colonne 1, tu peux faire un dictionnaire dont la clé est "Rouge" et la valeur est une liste avec les fruits.

Etape 1, tu vérifies si la colonne 1 est une clé existante.

Etape 2, si oui, tu regardes si la colonne 2 est contenue dans la liste


1
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 752
11 janv. 2023 à 11:56

Bonjour,

Je viens donc vers vous pour savoir par quel biais je dois partir, au niveau python. Par exemple, je n'ai jamais utilisé d'objets sur python. Dans ce cas là, dois-je les utiliser ? Ensuite, j'ai pensé à créer un grand tableau avec les types et valeurs regex possibles, ainsi je pourrais le parcourir pour vérifier les cohérences ou non. Peut-être que quelqu'un aura une idée que je n'aurais pas pensé.

Il faudrait voir de quels types on parle. En admettant que tu aies une fonction qui convertisse une chaîne dans un type cible, tu peux voir si cette fonction parvient à convertir la chaîne dans ce type et si elle plante en déduire que le type est incohérent.

C'est par exemple le cas de la fonction int(), qui tente de transformer une chaîne en entier. Note qu'il existe l'équivalent pour tous les types de bases en python (float, str, ...) mais pas pour les types évolués (dates, adresses réseaux, etc.). À moins que le type cible soit une classe dont le constructeur prend une chaîne en paramètre, il faut donc avoir une fonction de conversion dédiée et voir si celle-ci plante ou non.

Une autre manière de faire consiste comme tu le proposes à associer à chaque type son expression régulière et voir si celle-ci concorde. Pour les types communs, les expressions régulières sont généralement faciles à trouver en ligne. Typiquement pour les fichiers de logs, voir la notion de GROK.

Les autres vérifications sont plus simples : minuscules pour les types, supprimer les valeurs en doublon, format pour les dates, etc.

Ces vérifications ne sont pas très bien définies à ce stade pour comprendre ce que tu as exactement en tête, mais quoi qu'il en soit la structure de ton programme est en gros, lire le fichier CSV ligne par ligne, extraire le type et la valeur, vérifier si les deux correspondent. Chaque fonction de vérification (une par type) peut s'appuyer sur une fonction de conversion de type (cf int()), une expression rationnelle, une vérification de format, de doublons etc.

Peut-être que si tu nous donnes un exemple concret, on comprendra mieux ce que tu veux faire, mais je crains qu'il n'y ait pas de solution "miracle".

Bonne chance

0
Whismeril Messages postés 19039 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 mai 2024 932
11 janv. 2023 à 12:11

Bonjour

faut donc avoir une fonction de conversion dédiée et voir si celle-ci plante ou non.

heu c'est pas très propre comme façon de faire, la gestion d'erreur doit rester l'exception.

D'ailleurs, en général, on ne parle pas d'erreur mais d'exception.


0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 752
12 janv. 2023 à 00:42

Je ne crois pas avoir parlé d'erreur, et justement quand tu convertis une chaîne de caractère disons en entier, la fonction int lève une exception ValueError si ça n'est pas possible. Et même sur un type aussi simple, c'est quand même un peu plus simple d'écrire :

def is_int(s: str) -> bool:
    try:
        i = int(s)
        return True
    except ValueError:
        return False

... que :

import re

RE_INT = re.compile("[-|+]?[0-9]+")

def is_int(s: str) -> bool:
    return bool(RE_INT.match(s))

Du coup je ne vois pas en quoi ça n'est pas "propre". Et quand l'expression rationnelle devient hyper compliquée (par pour  une adresse IPv6) je pense que tu n'hésiteras pas à prendre la première option ;-)

0
Whismeril Messages postés 19039 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 mai 2024 932
12 janv. 2023 à 08:17

Ha si j'hésiterais longtemps.

Faire sciemment planter le programme pour vérifier un truc est contre nature. 

Un try ne devrait être utile qu'en cas d'imprévu total, et pas une fois sur 2.

Je chercherai donc autre chose pour vérifier et si je ne trouve pas, je prendrai une regex.

Mais la tienne comporte des erreurs, comme tu peux le voir ici https://regex101.com/r/hgfNmm/1

Chaque ligne (et donc chaque texte différent) retourne un match.

Une première correction (tester sur la ligne entière) https://regex101.com/r/hgfNmm/2 montre que le pipe est accepté, car 

"[-|+]"

veut dire "moins ou pipe ou plus"

Donc la regex que j'utiliserai serait https://regex101.com/r/hgfNmm/3

"^[-+]?\d+$"


Mais bon de toute façon Lynow n'a pas clairement défini ce qu'il appelle un type, Comme il a écrit en avoir plus de 200, j'ai pensé qu'il ne s'agissait pas d'un type de données, mais un type de produit ou autre chose dans le même principe.


0
Whismeril Messages postés 19039 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 mai 2024 932
12 janv. 2023 à 08:27

Y'a pas à se torturer l'esprit ça existe déjà https://datagy.io/python-isdigit/

0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 752 > Whismeril Messages postés 19039 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 mai 2024
12 janv. 2023 à 13:29

Faire sciemment planter le programme pour vérifier un truc est contre nature. 

Tu ne le fais pas planter puisque tu rattrapes l'exception. Et il y a plein de situation en programmation où tu n'as pas le choix, par exemple si tu veux vérifier qu'un contenu est téléchargeable.

Y'a pas à se torturer l'esprit ça existe déjà https://datagy.io/python-isdigit/

Tout à fait Whismeril, j'ai pris l'exemple des entiers pour rester volontairement simple, et dans ce cas particulier des entiers, isdigit est clairement la solution la plus indiquée. Mon propos concernait des types plus compliqués (des adresses IP, des dates, des heures, etc...) pour lesquels écrire l'expression rationnelle est une vraie torture. Pour t'en convaincre, compare les deux méthodes pour une adresse IPv6 (en prenant une expression régulière rigoureuse). Alors certes tu peux la trouver sur Internet, mais c'est une sacrée tartine :-)

0
Whismeril Messages postés 19039 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 mai 2024 932 > mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024
13 janv. 2023 à 07:21

Tu ne le fais pas planter puisque tu rattrapes l'exception. Et il y a plein de situation en programmation où tu n'as pas le choix, par exemple si tu veux vérifier qu'un contenu est téléchargeable.

Rattraper l'exception empêche la propagation du plantage à l'ensemble du programme, mais il a quand même planté...

Une exception ça perd du temps d'exécution (bon en Python, la vitesse n'est pas ce qu'on cherche, mais quand même). La fonction qui a planté a monopolisé des ressources, elle peut ne pas les avoir libérées et de plantage volontaire en plantage volontaire, on peut arriver à consommer toute la pile ou plus rarement tout le tas.


Bref, dans un cas où il y a une autre solution, non.

0
gsoul > Whismeril Messages postés 19039 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 mai 2024
13 janv. 2023 à 12:10

Bonjour, en python, on préfère demander pardon que la permission (comme bien des langages), j'ai la flemme d'aller chercher les références dans la pep de python.

0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 752 > gsoul
Modifié le 13 janv. 2023 à 15:27

Rattraper l'exception empêche la propagation du plantage à l'ensemble du programme, mais il a quand même planté...

  • Non, puisqu'il continue à s'exécuter. C'est d'ailleurs la différence entre une exception rattrapée et une exception non rattrapée. La première permet de "rattraper le coup" et de poursuivre l'exécution du programme, l'autre déclenche un plantage du programme.
  • C'est contrairement à ce que tu penses plus commun que tu ne le crois de "challenger" une fonction pour voir si elle va s'en sortir ou non. Par exemple en C, si on construit une application graphique windows basées sur les fonctions fournies par l'OS, il est commun d'utiliser send_message sans savoir si le message va être effectivement traité ou non, et de contrôler la valeur de retour pour prendre une décision.
  • Je conçois (et respecte) que ce ne soit pas ton style de programmation, et pour être totalement honnête avec toi, quand ça peut être éviter (cf ton exemple isdigit), c'est mieux de l'éviter. Mais ça ne veut pas dire que tu dois systématiquement t'en priver si ça simplifie considérablement le code ou si c'est la seule solution.

Une exception ça perd du temps d'exécution (bon en Python, la vitesse n'est pas ce qu'on cherche, mais quand même).

  • En C++ je te dirais qu'on peut être sensible à ce genre de considération, en python non.

La fonction qui a planté a monopolisé des ressources, elle peut ne pas les avoir libérées et de plantage volontaire en plantage volontaire, on peut arriver à consommer toute la pile ou plus rarement tout le tas.

  • Si le code python est bien écrit non. Par exemple si la fonction accède à un fichier (régulier ou socket) qui a été ouvert avec un context manager, celui-ci garantit que le file descriptor est correctement fermé.

on préfère demander pardon que la permission (comme bien des langages), j'ai la flemme d'aller chercher les références dans la pep de python.

  • Tout à fait, gsoul. Pour appuyer ce propos, voir cette discussion et ce lien qui oppose "EAFP" ("Easier to Ask for Forgiveness than Permission" : il est plus facile de demander pardon que la permission) et  "LBYL", ("Look Before You Leap" : regarder avant de bondir). Je pense que le PEP que tu évoques est le PEP 463.
0