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

Bibliothèques tierces Python Discussion :

Connexions multiples Python - Mysql


Sujet :

Bibliothèques tierces Python

  1. #1
    Membre régulier Avatar de raoulchatigre
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2004
    Messages : 99
    Points : 87
    Points
    87
    Par défaut Connexions multiples Python - Mysql
    Bonjour à tous,

    Après pas mal d'années à joongler entre C++, Perl, PHP et leur lib Mysql respectives. Je me met aujourd"hui à Python avec la lib mysql-python qui est basée sur l'API Mysql C.
    Voilà pour l'intro.

    Mon objectif c'est de créer un programme de nettoyage d'une énorme base de donnée, en évitant si possible que le programme se suce allègrement toute la mémoire du serveur. Et là c'est plus compliqué...
    Je m'explique par le code :
    Code python : 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
     
        def testData(self):
            print "On affiche toutes les valeurs qui vont être modifiées"
     
            # On observe tous les tuples concernés dans la table Document
            cursorDoc = self.dbConnect.cursor(cursors.SSCursor)
            queryDoc = "SELECT DocKey FROM Document WHERE Date < '20080101' "
            cursorDoc.execute(queryDoc)
            for (docKey,) in cursorDoc:
                # On compte le nombre d'éléments qui vont être supprimés dans les tables liées
                cursorCnt = cursor(cursors.SSCursor)
                tables = ("Tracing", "DocPage", "SubscriberDoc", "Document")
     
                for table in tables:
                    queryCnt = "SELECT count(*) FROM %s WHERE DocKey = '%s' " % (table, docKey)
                    cursorCnt.execute(queryCnt)
                    print cursorCnt
     
                cursorCnt.close()
            cursorDoc.close()

    et la réponse à l'exécution :
    Citation Envoyé par python CLI
    File "PurgeCB2.py", line 55, in testData
    cursorCnt.execute(queryCnt)
    File "build/bdist.linux-i686/egg/MySQLdb/cursors.py", line 166, in execute
    File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 35, in defaulterrorhandler
    _mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now")
    Exception _mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now") in <bound method SSCursor.__del__ of <MySQLdb.cursors.SSCursor object at 0x403254ec>> ignored
    Et bien j'ai l'honneur de vous apprendre que ce code ne fonctionne pas car :
    "You can't really have multiple cursors on the same connection at the same
    time."
    Traduction : c'est impossible d'avoir plusieurs curseurs en même temps.
    C'est une limitation de l'api Mysql-C sur laquelle est basé python-mysql.

    A noter que j'utilise des SSCursor qui conservent le résultat côté serveur ce qui est à l'origine du problème. Mais si je veux éviter de faire enfler ma mémoire, je fais comment ?

    Si vous avez des idées je suis preneur...

    Merci,
    Ercete

  2. #2
    Membre régulier Avatar de raoulchatigre
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2004
    Messages : 99
    Points : 87
    Points
    87
    Par défaut
    Bien, je n'ai pas encore trouvé de parade à mon surplus de consommation mémoire.

    En revanche à force de tests, je viens de comprendre un peu mieux le fonctionnement des Cursor

    le code suivant par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    import MySQLdb
    from MySQLdb import cursors
     
    bdd = MySQLdb.connect("serv","base","user","pass")
    c = bdd.cursor(cursors.SSCursor)
    c.execute( "SELECT * FROM Table1" )
    c.execute( "SELECT * FROM Table2" )
    génère l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> c.execute( "SELECT * FROM Table2" )
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "build/bdist.linux-i686/egg/MySQLdb/cursors.py", line 166, in execute
      File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 35, in defaulterrorhandler
    _mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now")
    Cela ne fonctionne pas et pour cause pour qu'un curseur puisse être utilisable avec execute, il faut absolument qu'on soit arrivé au bout du jeu de résultat
    soit avec un c.fetchall(), des c.fetchone() ou encore une boucle for sur le curseur.

    EDIT: la fonction c.nextset() semble permettre de passer à un nouveau jeu de résultat et ainsi continuer à faire des requêtes.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par raoulchatigre Voir le message
    Bonjour à tous,

    Après pas mal d'années à joongler entre C++, Perl, PHP et leur lib Mysql respectives. Je me met aujourd"hui à Python avec la lib mysql-python qui est basée sur l'API Mysql C.
    Voilà pour l'intro.

    Mon objectif c'est de créer un programme de nettoyage d'une énorme base de donnée, en évitant si possible que le programme se suce allègrement toute la mémoire du serveur. Et là c'est plus compliqué...
    Je m'explique par le code :
    Code python : 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
     
        def testData(self):
            print "On affiche toutes les valeurs qui vont être modifiées"
     
            # On observe tous les tuples concernés dans la table Document
            cursorDoc = self.dbConnect.cursor(cursors.SSCursor)
            queryDoc = "SELECT DocKey FROM Document WHERE Date < '20080101' "
            cursorDoc.execute(queryDoc)
            for (docKey,) in cursorDoc:
                # On compte le nombre d'éléments qui vont être supprimés dans les tables liées
                cursorDel = cursor(cursors.SSCursor)
                tables = ("Tracing", "DocPage", "SubscriberDoc", "Document")
     
                for table in tables:
                    queryCnt = "SELECT count(*) FROM %s WHERE DocKey = '%s' " % (table, docKey)
                    cursorCnt.execute(queryCnt)
                    print cursorCnt
     
                cursorCnt.close()
            cursorDoc.close()

    et la réponse à l'exécution :


    Et bien j'ai l'honneur de vous apprendre que ce code ne fonctionne pas car :
    "You can't really have multiple cursors on the same connection at the same
    time."
    Traduction : c'est impossible d'avoir plusieurs curseurs en même temps.
    C'est une limitation de l'api Mysql-C sur laquelle est basé python-mysql.

    A noter que j'utilise des SSCursor qui conservent le résultat côté serveur ce qui est à l'origine du problème. Mais si je veux éviter de faire enfler ma mémoire, je fais comment ?

    Si vous avez des idées je suis preneur...

    Merci,
    Ercete
    Accessoirement je remarque que t'as un cursorCnt.execute() mais je ne vois nulle part de "cursorCnt=machin.cursor()". De plus tu ne fais qu'un close() hors de ta boucle alors que moi j'aurais fait le cursor+close dans la boucle. Mais sinon, pourquoi ne pas essayer un truc ressemblant à ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for table in tables:
        queryCnt = "SELECT count(*) FROM %s WHERE DocKey in (SELECT DocKey FROM Document WHERE Date < '20080101' )" % (table)
    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]

  4. #4
    Membre régulier Avatar de raoulchatigre
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2004
    Messages : 99
    Points : 87
    Points
    87
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Accessoirement je remarque que t'as un cursorCnt.execute() mais je ne vois nulle part de "cursorCnt=machin.cursor()".
    Oui j'ai mal copié mon code, c'est cursorDel qui s'apelle cursorCnt en fait. (edit : c'est corrigé)

    De plus tu ne fais qu'un close() hors de ta boucle alors que moi j'aurais fait le cursor+close dans la boucle. Mais sinon, pourquoi ne pas essayer un truc ressemblant à ça
    Heu, je crois que tu n'as pas tout saisi : je n'utilise pas de fetchall, je fais un parcours séquentiel du résultat (sans doute un fetchone derrière), utiliser un fetchall risque de m'importer le jeu de résultat en mémoire ce qui revient à utiliser un Cursor standard, ce que je veux éviter. Le parcours que j'utilise ne met en mémoire côté client que le contenu d'une seule ligne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for table in tables:
        queryCnt = "SELECT count(*) FROM %s WHERE DocKey in (SELECT DocKey FROM Document WHERE Date < '20080101' )" % (table)
    Ce n'est pas une mauvaise idée, le truc c'est que le requête de count(*) n'est qu'un exemple, en réalité je risque de faire des UPDATE ou des DELETE en fonction de certains paramètres. Je ne sais pas si les DELETE/UPDATE fonctionnent avec les requêtes imbriquées (je ne vois pas ce qui en empêcherai). De plus avec ta solution je n'ai plus la nécessité d'utiliser des SSCursors. En revanche si je veux faire un traitement en python au préalable sur des valeurs de ma première requête, je ne peux pas.

    Pour mon cas particulier, j'ai trouvé une solution qui me permet de me passer des SSCursors pour le moment.
    Mais je penses que la problématique fondamentale est toujours valable.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par raoulchatigre Voir le message
    En revanche si je veux faire un traitement en python au préalable sur des valeurs de ma première requête, je ne peux pas.
    Bon, ok je comprends ton idée. Mais si t'as droit qu'à un seul curseur à la fois par id de connection, n'as-tu pas droit à plusieurs id de connection dans ton code ???
    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]

  6. #6
    Membre régulier Avatar de raoulchatigre
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2004
    Messages : 99
    Points : 87
    Points
    87
    Par défaut
    Effectivement !
    Vu que mon objet de connexion est global, je n'ai pas cherché à en créer un nouveau.
    Mais cela doit fonctionner impec !

    Quand j'aurai un peu de temps je testerai cette solution,
    pour le moment on je suis obligé de refoutre les mains dans du perl et j'en ai plein les doigts, c'est dégeulasse.

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par raoulchatigre Voir le message
    pour le moment on je suis obligé de refoutre les mains dans du perl et j'en ai plein les doigts, c'est dégeulasse.
    Yes !!! Quand j'ai voulu apprendre un langage l'été dernier, j'ai eu à choisir entre Perl et Python... et j'ai choisi Python parce que plus récent. Bon finalement je ne regrette pas
    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]

Discussions similaires

  1. [BDD] Erreur dans la connexion à une base MySQL
    Par dodo10 dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 24/01/2005, 19h52
  2. [JSP] Connexion à une base mysql
    Par Jovial dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 20/04/2004, 14h04
  3. Problème de connexion au serveur MYSQL
    Par ETOKA dans le forum Outils
    Réponses: 2
    Dernier message: 27/11/2003, 09h28
  4. [JBuilder]connexion postgres ou mysql via DataExpress
    Par rebolon dans le forum JBuilder
    Réponses: 12
    Dernier message: 07/08/2003, 16h45

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