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 :

Pyodbc passage de Py2.7 vers Py3.6, pb encodage entre module


Sujet :

Python

  1. #1
    En attente de confirmation mail
    Homme Profil pro
    Géomaticien (plutôt sur Arcgis...)
    Inscrit en
    Juillet 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Géomaticien (plutôt sur Arcgis...)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juillet 2013
    Messages : 49
    Points : 29
    Points
    29
    Par défaut Pyodbc passage de Py2.7 vers Py3.6, pb encodage entre module
    Bonjour,

    Je tente de passer un code qui fonctionnait bien sous 2.7 vers py 3.6 (je suis en cours de migration complète entre 2.7 et 3.x

    J'ai créé un module de connexion à notre SQL2008, pour passer les commandes SQL : MonModuleSQL.py.
    J'appel ce module dans les scripts où j'en ai besoin.

    dans mon cas actuel, dans MonModuleSQL, j'ai la définition suivante:
    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
    21
    22
    23
    24
     
    # -*- coding: utf-8 -*-
    import pyodbc
     
    def select_MSSQL(select_MS):
        """ Connexion au serveur MSSQL 
        passage de la commande SQL select en parametre
        renvoi la liste"""
        server = 'MON_SQL'
        database = 'data'
        username = "sa"
        password = 'Pword'
     
        param_connect = ('DRIVER={SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+password+";")
     
        cnxn = pyodbc.connect(param_connect) # connexion a SQL
        # cnxn.setencoding(str, encoding='cp1252') # Necessaire en 2.7, mais visiblement non connu en 3.9
     
        cursor = cnxn.cursor()#cursor pour passage des commandes suivantes
        cursor.execute(select_MS) #execute la requete SQL
     
        rows = cursor.fetchall()
        cnxn.commit() #fermeture connexion
        return rows
    Si je fais un test, en restant dans ce MonModuleSQL.py(en bas du module), j'excute mon code suivant, ça passe sans soucis.
    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
     
    reference,id = 'A260', 'ID2001'
     
    Rq_SQL ="""SELECT  SUBSTRING(data.dbo.Table1.Date_crea,3,2),
    CAST({fn DAYOFYEAR(data.dbo.Table1.Date_crea)} AS varchar(3)), data.dbo.Table1.nom,
    data.dbo.Table1.libelle, data.dbo.Table1.memo,
    data.dbo.Table2.identifiant 
    FROM**data.dbo.Table2 INNER JOIN data.dbo.Table2 AS Table2_1 ON 
    data.dbo.Table2.dossier = Table2_1.source INNER JOIN 
    data.dbo.Table1 ON Table2_1.dossier = data.dbo.Table1.dossier 
    WHERE  (data.dbo.Table1.ref = '%s') 
    AND (data.dbo.Table2.identifiant='%s')"""%(reference,id)
     
    retour_MSSQL = select_MSSQL(Rq_SQL)
    print r(etour_MSSQL)
    résultat OK

    Par contre, lorsque j'appel cette définition depuis un autre script.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    # -*- coding: utf-8 -*-
    sys.path.append(r"\\SRV_FICHIERS\...\MonModuleSQL.py")
    import MonModuleSQL as odbc
    où j'ai des boucles qui déterminent les valeurs utilisées en where, et reprosuisent ma commande SQL:
    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
     
    # -*- coding: utf-8 -*-
    [sys.path.append...]
    [...]
    reference = liste[0]
    id = liste[1]
    [...]
     
    Rq_SQL ="""SELECT  SUBSTRING(data.dbo.Table1.Date_crea,3,2),
    CAST({fn DAYOFYEAR(data.dbo.Table1.Date_crea)} AS varchar(3)), data.dbo.Table1.nom,
    data.dbo.Table1.libelle, data.dbo.Table1.memo,
    data.dbo.Table2.identifiant 
    FROM**data.dbo.Table2 INNER JOIN data.dbo.Table2 AS Table2_1 ON 
    data.dbo.Table2.dossier = Table2_1.source INNER JOIN 
    data.dbo.Table1 ON Table2_1.dossier = data.dbo.Table1.dossier 
    WHERE  (data.dbo.Table1.ref = '%s') 
    AND (data.dbo.Table2.identifiant='%s')"""%(reference,id)
    puis j'appel ma définition odbc.select_MSSQL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     retour_MSSQL =odfbe.select_MSSQL(Rq_SQL)
    J'ai le message d'erreur suivant:

    File "\\SRV_FICHIERS\...\MonModuleSQL.py", line 138, in select_MSSQL
    cursor.execute(select_MS) #execute la requete SQL

    ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Syntaxe incorrecte vers '\xa0'. (102) (SQLExecDirectW)")


    '\xa0' correspond aux espaces dans le texte, c'est bien cela?
    J'ai donc un problème d'encodage lors de l’envoie de ma requête SQL en string , vers le module appelé en externe (puisque la ma requête passe bien, lorsque qu'elle est exécuter en directe dans le module externe).
    J'ai tenté pas mal de chose:
    - Rq_SQL =u"""SELECT SUBSTRING(...
    - Rq_SQL.encode("CP1252")
    et je ne sais plus, tellement j'ai fait de tests...

    Mais rien n'y fait... ma commande SQL arrive mal encodé dans mon module SQL.

    Quelqu'un verrait-il une piste svp?
    Merci

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par little_kevin Voir le message
    Quelqu'un verrait-il une piste svp?
    Lorsque vous faites une requête "avec paramètres" vous n'êtes pas supposé construire la chaîne de caractères mais le faire faire par le pilote i.e.
    ...execute('SELECT ...' % (....)) doit être ...execute('SELECT ...', (....)).
    Et après avoir vérifié dans la documentation du pilote les caractères de substitution à utiliser (c'est pas toujours %s).

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

  3. #3
    En attente de confirmation mail
    Homme Profil pro
    Géomaticien (plutôt sur Arcgis...)
    Inscrit en
    Juillet 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Géomaticien (plutôt sur Arcgis...)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juillet 2013
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    Je comprend ta réponse wiztricks.

    Mais il y a quand même quelque chose qui me chiffonne.
    Si je met ma définition SQL et la construction de ma chaine de caractère dans le même script, ça passe très bien.
    Alors pourquoi cela ne fonctionne pas, avec les mêmes commandes commandes de construction de chaine, lorsque j'appel la définition depuis autre fichier...

    Désolé je suis autodidacte dans python depuis 5 ans (avec qques MOOC quand même). Mais je pense qu'il manque encore pas mal de notions...

    Merci

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par little_kevin Voir le message
    Si je met ma définition SQL et la construction de ma chaine de caractère dans le même script, ça passe très bien.
    Alors pourquoi cela ne fonctionne pas, avec les mêmes commandes commandes de construction de chaine, lorsque j'appel la définition depuis autre fichier...
    Je suis d'accord, c'est une question intéressante car il n'y a pas de raisons pour qu'une chaîne de caractères construite dans un module "change" lorsqu'on appelle une fonction dans un autre module.
    Ceci dit, avant de se plonger la dedans, il faudrait pouvoir reproduire en dehors de votre contexte (et avec une fonction ordinaire).
    Ce qui prendra un temps indéterminé et une probabilité non nulle de ne pas aboutir (car s'il y a avait ce genre de problème avec Python, çà se saurait).

    Par contre, modifier votre code pour faire votre requête proprement ne prend pas beaucoup de temps.

    Mon expérience des migrations est que le code écrit un peu trop vite y survit rarement (çà à même un nom: "la dette technique").
    Après on peut passer des heures à trouver le pourquoi du comment... vous vous retrouverez toujours à devoir ré-écrire votre code plus proprement.
    Autant gagner du temps en commençant par là.

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

  5. #5
    En attente de confirmation mail
    Homme Profil pro
    Géomaticien (plutôt sur Arcgis...)
    Inscrit en
    Juillet 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Géomaticien (plutôt sur Arcgis...)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juillet 2013
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    Merci. Du coup je tente de reprendre mon code.

    Ainsi ma requête devient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Rq_SQL ="""SELECT  SUBSTRING(data.dbo.Table1.Date_crea,3,2),
    CAST({fn DAYOFYEAR(data.dbo.Table1.Date_crea)} AS varchar(3)), data.dbo.Table1.nom,
    data.dbo.Table1.libelle, data.dbo.Table1.memo,
    data.dbo.Table2.identifiant 
    FROM**data.dbo.Table2 INNER JOIN data.dbo.Table2 AS Table2_1 ON 
    data.dbo.Table2.dossier = Table2_1.source INNER JOIN 
    data.dbo.Table1 ON Table2_1.dossier = data.dbo.Table1.dossier 
    WHERE  (data.dbo.Table1.ref = ?) 
    AND (data.dbo.Table2.identifiant=?)"""
    et mes variables:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    values = ('A260', 'ID2001')
    Dans ma définition mon execute devient:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cursor.execute(select_MS,value)
    Appel de ma définition
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    retour_MSSQL = select_MSSQL(Rq_SQL,values)
    Je viens de le tenter dans le même fichier...
    Mais j'ai toujours le message d'erreur pour l'espace et et une erreur en plus:
    ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Syntaxe incorrecte vers '\xa0'. (102) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Impossible de préparer les instructions. (8180)")

    Pour la formule sql, je me suis insprié de ce ticket (mais mon anglais es loin du niveau necessaire pour bien l'appliquer je crois :oops):
    https://stackoverflow.com/questions/...or-a-parameter

    Merci

  6. #6
    En attente de confirmation mail
    Homme Profil pro
    Géomaticien (plutôt sur Arcgis...)
    Inscrit en
    Juillet 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Géomaticien (plutôt sur Arcgis...)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juillet 2013
    Messages : 49
    Points : 29
    Points
    29
    Par défaut
    En fait tout mon code est bien. tout fonctionne!
    Mais en relisant mon post, dans ma requête SQL issu d'un copier-coller de ma fenêtre Spyder, je viens de voir 2 caractères que je n'ai pas dans Spyder!
    après mon FROM, il y a '**' à la place de mon espace...

    Dans spyder je viens de supprimer puis remplacer l'espace que je vois. Et tout est bon.

    Toute mes formules indiquées ci-dessus fonctionne !

    Merci beaucoup de ton aide wiztricks et navré pour la perte de temps induite.

    Cdt

Discussions similaires

  1. Passage de parametre Access vers Excel
    Par climz dans le forum Access
    Réponses: 2
    Dernier message: 05/05/2006, 15h07
  2. [débutant]Passage GUI de Swing vers SWT
    Par Méta dans le forum AWT/Swing
    Réponses: 9
    Dernier message: 04/05/2006, 13h29
  3. Réponses: 2
    Dernier message: 24/03/2005, 10h20
  4. Réponses: 2
    Dernier message: 17/02/2005, 13h48
  5. Passage du type integer vers varchar sur clé primaire
    Par GMI dans le forum Bases de données
    Réponses: 2
    Dernier message: 07/01/2005, 09h09

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