IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Reconnaissance d'un type de valeur


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 240
    Par défaut Reconnaissance d'un type de valeur
    Bonjour à tous,

    J'apprends le langage python en même temps que le dev d'un script de synchronisation d'une base Oracle et Mysql. Le script est tout simple, je fais une requête sqlplus via subprocess, le résultat est écrit dans un fichier csv et ensuite je lis ce fichier pour recréer un fichier sql et le pousser dans mysql. Je suis obligé de passer par l'étape csv car j'applique des traitements avant import.

    Mon problème est dans la reconnaissance du type d'une chaîne. Par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    REPLACE INTO matable('monchamp') VALUES(020050)
    est totalement différente de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    REPLACE INTO matable('monchamp') VALUES("020050")
    Et bien sûr c'est cette dernière que mysql attend.

    Dans le csv, 020050 est enregistré sans les " et à la lecture type() de python le reconnaît comme un int et il passe au travers de isalnum() (la valeur peut contenir des lettres et chiffres). J'ai bien pensé à faire une condition pour chaque champs mais il y en a bien trop.

    Est-ce qu'il y aurait une autre méthode pour détecter le type de chaîne ?

    Merci d'avance.

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par flipflip Voir le message
    Mon problème est dans la reconnaissance du type d'une chaîne. Par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    REPLACE INTO matable('monchamp') VALUES(020050)
    est totalement différente de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    REPLACE INTO matable('monchamp') VALUES("020050")
    Oui, mais ça c'est un souci spécifquement SQL. Si la colonne "monchamp" est de type "char" et dérivé (varchar, text) il faut évidemment lui donner une string à bouffer.

    Citation Envoyé par flipflip Voir le message
    Dans le csv, 020050 est enregistré sans les " et à la lecture type() de python le reconnaît comme un int
    C'est donc à l'écriture du csv que le souci se pose. Tu aurais dû y mettre des guillemets.

    Citation Envoyé par flipflip Voir le message
    et il passe au travers de isalnum() (la valeur peut contenir des lettres et chiffres). J'ai bien pensé à faire une condition pour chaque champs mais il y en a bien trop.

    Est-ce qu'il y aurait une autre méthode pour détecter le type de chaîne ?
    Là je ne pige pas la question. C'est quoi pour toi un "type de chaine" ? Une chaine c'est une chaine, c'est tout. type("123") ou type("Hello") c'est la même chose.
    Ensuite tu peux détecter la différence entre "123" et "Hello" en le passant par int(). Dans le premier cas ça te ressort int(123) tandis que dans l'autre t'as une exception ValueError que tu peux catcher via un try...except.

    Mais en fait je ne pige même pas ton souci. MySQL attend un truc style REPLACE INTO matable('monchamp') VALUES("020050") tu lui envoies alors "REPLACE INTO matable('monchamp') VALUES(\"%06d\")" % variable. Ou mieux, tu écris (comme je l'ai fait) une fonction qui rajoute automatiquement des guillemets aux strings et tu passes par cette fonction pour écrire tes ordres SQL
    Exemple
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> setIFS=lambda txt: "{0}{1}{0}".format('"', txt)
    >>> var=20050
    >>> print("REPLACE INTO matable('monchamp') VALUES(%s)" % setIFS("%06d" % var))
    REPLACE INTO matable('monchamp') VALUES("020050")

    Et tu devrais te mettre rapidement à Python3 car plus tu tarderas plus ça se fera dans la douleur.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 746
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 746
    Par défaut
    Salut,

    Citation Envoyé par flipflip Voir le message
    J'apprends le langage python en même temps que le dev d'un script de synchronisation d'une base Oracle et Mysql. Le script est tout simple, je fais une requête sqlplus via subprocess, le résultat est écrit dans un fichier csv et ensuite je lis ce fichier pour recréer un fichier sql et le pousser dans mysql. Je suis obligé de passer par l'étape csv car j'applique des traitements avant import.
    Normalement la lecture de la base de donnée retourne un tuple avec les bons types. Si on l'écrit dans un fichier CSV tout devient chaîne de caractères et savoir si "21234" est un entier ou une chaîne de 5 caractères est possible en écrivant les chaines des caractères avec des quotes (pour les différentier des entiers) - ce qui est une option à l'écriture des fichiers CSV...
    Si on ne le fait pas, ben l'information (le type des différentes colonnes) est à transporter en meta data (à la main).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 240
    Par défaut
    Salut,

    Avec un exemple de données stocké dans la table cela sera peut être plus simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    TBL_0  |TO_CHAR(A.DAT_0,'DD-MM-YYYY')|HOU_0 |EVT_0 |ID1_0         |ID2_0    |COL_0       |NVAL_0                  |
    -------+-----------------------------+------+------+--------------+---------+------------+------------------------+
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |SOHNUM      |NORHIL21070001          |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |ZSTATUT     |1                       |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPAADD      |C02                     |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPDNAM(0)   |PM C02                  |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPDNAM(1)   |                        |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPDADDLIG(0)|Prénom Nom      |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPDADDLIG(1)|25 rue de paris|
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPDADDLIG(2)|                        |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPDPOSCOD   |69101                   |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |BPDCTY      |Une VILLE            |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |CUSORDREF   |                        |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |PJT         |                        |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |ORDDAT      |01072021                |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |SHIDAT      |01072021                |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |DEMDLVDAT   |06072021                |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |LASDLVDAT   |31121599                |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |REP(0)      |999                     |
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |REP(1)      |                        |
    Cette table est alimenté par l'ERP lorsqu'une action est réalisée sur certains champs (audit). C'est pour cette raison qu'il y a un enregistrement par action (EVT_0) et COL_0. Ensuite toutes les X minutes j'exporte ces enregistrements pour reproduire ces actions dans une base Mysql utilisé par une BI.

    Dans mon fichier csv cela correspond à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SORDER;01-07-2021;163840;INSERT;NORHIL21070001; ;SOHNUM;NORHIL21070001
    SORDER;01-07-2021;163840;INSERT;NORHIL21070001; ;ZSTATUT;1
    SORDER;01-07-2021;163840;INSERT;NORHIL21070001; ;BPAADD;C02
    SORDER;01-07-2021;163840;INSERT;NORHIL21070001; ;BPDADDLIG(0);Prénom Nom 
    SORDER;01-07-2021;163840;INSERT;NORHIL21070001; ;BPDNAM(1);
    SORDER;01-07-2021;163840;INSERT;NORHIL21070001; ;BPDNAM(0);PM C02
    [...]
    Dans cette exemple (une commande client)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TBL_0  |TO_CHAR(A.DAT_0,'DD-MM-YYYY')|HOU_0 |EVT_0 |ID1_0         |ID2_0    |COL_0       |NVAL_0                  |
    -------+-----------------------------+------+------+--------------+---------+------------+------------------------+
    SORDER |01-07-2021                   |163840|INSERT|NORHIL21070001|         |SOHNUM      |NORHIL21070001          |
    Correspond à "Le numéro de commande (NORHIL2107001 colonne NVAL_0) est inséré dans le champ SOHNUM de la table SORDER"

    Mon objectif est de transposer toutes les actions pour une même table en une seule ligne sql. En reprenant le jeu de données en sql cela deviendrait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO sorder(sohnum, zstatut, bpaadd, bpdnam, [...] VALUES("NORHIL21070001", 1, "C02", "PM C02", [...])

    Normalement la lecture de la base de donnée retourne un tuple avec les bons types. Si on l'écrit dans un fichier CSV tout devient chaîne de caractères et savoir si "21234" est un entier ou une chaîne de 5 caractères est possible en écrivant les chaines des caractères avec des quotes (pour les différentier des entiers) - ce qui est une option à l'écriture des fichiers CSV...
    Probablement lorsque c'est python qui requête directement Oracle, moi je passe par un fichier csv intermédiaire qui est généré par sqlplus.

    C'est donc à l'écriture du csv que le souci se pose. Tu aurais dû y mettre des guillemets.
    Malheureusement au moment de la requête je ne connais pas à l'avance le type de données dans le champs et je n'ai pas la main sur la base (ERP), ni la structure de la table. Je pourrais monter une table de correspondance basé sur le nom du champ mais cela va vite devenir l'enfer à maintenir.

    Et tu devrais te mettre rapidement à Python3 car plus tu tarderas plus ça se fera dans la douleur.
    Je fais les deux en parallèle, pour le moment je suis obligé de le faire en 2 car le serveur qui exploite la base est pas très à jour... Merci la dette technique

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 746
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 746
    Par défaut
    Salut,

    Citation Envoyé par flipflip Voir le message
    Malheureusement au moment de la requête je ne connais pas à l'avance le type de données dans le champs et je n'ai pas la main sur la base (ERP), ni la structure de la table. Je pourrais monter une table de correspondance basé sur le nom du champ mais cela va vite devenir l'enfer à maintenir.
    Certes... mais çà veut juste dire qu'on va devoir utiliser une heuristique pour deviner le type des données ou arbitrairement décider que toutes les données sont des chaines de caractères.

    Ce qui dans tous les cas n'est pas encore un sujet de programmation mais d'abord d'arbitrage.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 240
    Par défaut
    Certes... mais çà veut juste dire qu'on va devoir utiliser une heuristique pour deviner le type des données ou arbitrairement décider que toutes les données sont des chaines de caractères.
    Les basculer toutes en chaînes n'est pas possible car la BI détecte le type de valeur et adapte suivant le cas les fonctionnalités sur les champs.

    J'ai continué à faire des essais avec ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
            for key in tabH.keys():
                    table = tabH[key]["tbl"]
                    col0 = tabH[id1]["col0"] = "sohnum"
                    for subkey, values in tabH[key].items():
                            if(subkey != "tbl"):
                                    sqlcol.append(subkey)
                                    if(values == "020050"):
                                            print(type(values))
     
                                    if(values.isalnum()):
                                            if(values == "020050"):
                                                    print("Valeur alnum : " + values)
                                            sqlval.append("\"" + values + "\"")
                                    elif(values.isdigit()):
                                            if(values == "020050"):
                                                    print("Valeur digit : " + values)
                                            sqlval.append(values)
                                    else:
                                            sqlval.append("\"" + values + "\"")
    Ce qui donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <type 'str'>
    Valeur alnum : 020050
    Jusque là tout va bien, mais si j'inverse les contrôles isalnum et isdigit alors la valeur sera détecté comme un digit... pas très fiable comme contrôle

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 746
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 746
    Par défaut
    Citation Envoyé par flipflip Voir le message
    Jusque là tout va bien, mais si j'inverse les contrôles isalnum et isdigit alors la valeur sera détecté comme un digit... pas très fiable comme contrôle
    Certes mais c'est juste parce que vous l'avez codé comme çà.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Problème de type de valeur
    Par bobic dans le forum Langage
    Réponses: 4
    Dernier message: 16/08/2006, 09h53
  2. Test sur le type de valeur
    Par mevardy dans le forum Langage SQL
    Réponses: 4
    Dernier message: 07/08/2006, 13h43
  3. Type de valeur renvoyé ??
    Par Golork dans le forum Access
    Réponses: 1
    Dernier message: 27/06/2006, 17h59
  4. tests sur le type de valeurs
    Par dor_boucle dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 16/03/2006, 14h10
  5. [Base de Registre] Nouveaux type de valeur !?
    Par Lung dans le forum Langage
    Réponses: 4
    Dernier message: 07/04/2004, 10h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo