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

PyQt Python Discussion :

Accès Base de données QSqlite3 avec plusieurs Thread.


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Analyste programmeur
    Inscrit en
    Septembre 2015
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Algérie

    Informations professionnelles :
    Activité : Analyste programmeur
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2015
    Messages : 148
    Par défaut Accès Base de données QSqlite3 avec plusieurs Thread.
    Bonjour,

    Depuis plusieurs jours je cherche une solution à mon problème d'accès à la BD SQlite3 avec plusieurs threads.
    Ma fonction d'accès à la BD :

    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
     
    def ouvrecnx(self):
     
        basedonnee = os.path.join(CONFIG_DATABASE_PATH, CONFIG_DATABASE_NAME)
        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName(basedonnee)
     
        if not db.open():
            QMessageBox.critical(None, "Problème d'accès à la base de données \n",
                                 "Impossible d'établir une connexion à la base de données.\n"
                                 "Cliquer Annuler pour sortir.",
                                 QMessageBox.Cancel)
            return False
        else:
            return db
    et le code de lancement des threads

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    t1 = threading.Thread(name='Tables Temporaires1', target=self.creation_tables_tmp1)
    t2 = threading.Thread(name='Tables Temporaires2', target=self.creation_tables_tmp2)
     
    t1.start()
    print(t1.name)
     
    t2.start()
    print(t2.name)
    D'après la doc, pour chaque thread = une connexion à la DB, mais d'une par dans www.sqlit.org il y' a la notion de "SQLITE_CONFIG_MULTITHREAD" que je n'ai pas pu l'intégrer dans mon code
    et d'autre par j'ai trouvé un bout de code en C++ qui génère d'une manière automatique la connexion à DB avec un nom différent

    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
     
    QSqlDatabase DBUtil::openDataBase()
    {
        quint32 value = QRandomGenerator::global()->generate();
        QSqlDatabase db;
        if ( true == QSqlDatabase::contains(QString::number(value)))
        {
            db = QSqlDatabase::database(QString::number(value));
        }
        else
        {
            db = QSqlDatabase::addDatabase("QSQLITE", QString::number(value));
            db.setDatabaseName("xxx.db");
        }
     
        if (false == db.open())
        {
            qDebug() << db.lastError().text();
        }
        return db;
    }
    Merci de bien m'aider.

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je n'ai peut-être pas bien compris le problème, mais à mon avis, sqlite3 n'est pas multitâche. Pour plusieurs accès simultanées à une même base de données, il faut se tourner vers un vrai serveur (mysql, postgresql, ...).

  3. #3
    Membre confirmé
    Homme Profil pro
    Analyste programmeur
    Inscrit en
    Septembre 2015
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Algérie

    Informations professionnelles :
    Activité : Analyste programmeur
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2015
    Messages : 148
    Par défaut
    Bonjour Tyrtamos,

    Ce n'est pas du multitâche que je voudrais, mon souhait est de pouvoir lancer plusieurs requêtes SQL de SELECT en même temps sur une même BD sqlite3.
    C'est une application desktop.

    Et ci-dessous les messages d'erreur qui s'affichent :

    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
     
    Création Tables Temporaires1
    WARNING:
    QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
     
    WARNING:
    QSqlQuery::prepare: database not open
     
    WARNING:
    QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
     
    Création Tables Temporaires2
     
    WARNING:
    QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
    WARNING:
    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is Fenetre(0x23689d61960), parent's thread is QThread(0x23686332860), current thread is QThread(0x2369125f5a0)

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 759
    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 759
    Par défaut
    Salut,

    Essayez avec des QThreads (et réfléchissez à ce que vous a dit Tyrtamos).

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

  5. #5
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Puisque sqlite3 n'est pas un serveur, il ne faut pas s'attendre à ce qu'il sache répondre à plusieurs requêtes simultanées. Mais si on a une bonne raison d'envoyer plusieurs requêtes à partir de plusieurs threads, il faudrait que ces requêtes soient placées dans une pile FIFO (First In First Out) pour se présenter une à une à sqlite3. Il faudra vérifier que la pile utilisée contient, ou est associée à, un verrou (lock) pour la protéger des collisions d'accès. Une simple "list" avec un verrou et quelques méthodes de traitement prédéfinies conviendrait.

    Peut-être faudrait-il un thread de plus pour assurer cette interface, ce qui permettra de "sérialiser" les requêtes pour sqlite3:
    1- attendre la requête suivante dans la pile s'il en a une
    2- la présenter à sqlite3 et attendre sa réponse
    3- recevoir sa réponse et la renvoyer au demandeur
    4- revenir en 1
    En fait, on fait de façon simplifiée le boulot d'un serveur...

    Ça me fait penser à un truc que j'ai fait il y a longtemps pour assurer des travaux par plusieurs threads. J'avais utilisé une pile de classes, chaque classe contenant en gros:
    - l'identifiant du thread demandeur
    - la requête demandée
    - la place pour la future réponse
    - un drapeau pour indiquer que la réponse est disponible
    - tout autre information pertinente pour le sujet

    Ce qui fait que chaque thread peut mettre sa requête sur la pile commune, attendre quelle soit traitée, et la sortir de la pile pour la suite de son boulot. Cela permet aussi de gérer la file d'attente des requêtes non résolues et, si nécessaire, de "modérer" la vigueur des threads demandeurs...

    En fait, la pile est un objet commun de communication entre les threads.

    Tout cela est assez délicat à mettre au point, mais quand c'est fait, ça marche très bien!

  6. #6
    Membre confirmé
    Homme Profil pro
    Analyste programmeur
    Inscrit en
    Septembre 2015
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Algérie

    Informations professionnelles :
    Activité : Analyste programmeur
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2015
    Messages : 148
    Par défaut
    Bonjour wiztricks,

    J'ai utilisé QThread comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    t1 = QThread.thread(name='Création Tables Temporaires1', target=self.creation_tables_tmp1)
    t2 = QThread.thread(name='Création Tables Temporaires2', target=self.creation_tables_tmp2)
    Et voici le message d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    t1 = QThread.thread(name='Création Tables Temporaires1', target=self.creation_tables_tmp1)
    TypeError: thread() takes no keyword arguments
    Mais pour vous Tyrtamos, que comme vous venez de dire "Tout cela est assez délicat à mettre au point, mais quand c'est fait, ça marche très bien!"
    Y a t'il un petit exemple ...
    Merci.

  7. #7
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par noureddine1967 Voir le message
    Mais pour vous Tyrtamos, que comme vous venez de dire "Tout cela est assez délicat à mettre au point, mais quand c'est fait, ça marche très bien!"
    Y a t'il un petit exemple ...
    Le travail que j'avais fait est assez différent du vôtre: un thread fournissait des expressions mathématiques à calculer et 10 threads étaient là pour les calculer et renvoyer le résultat. Les threads étaient en fonctionnement permanent, et allaient chercher du travail quand le précédent était fini. Vous pouvez vous en inspirer. C'est ici:

    https://python.jpvweb.com/python/mes...d_tableaublanc

    Attention: c'est en Python 2. Mais la logique n'a pas changée.

    Quand à choisir entre threading et QThread, ce dernier a un avantage: il permet d'envoyer des messages (.emit()), ce que je n'avais pas en 2008. Quand je développe en PyQt5, j'utilise QThread dans tous les cas.

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 759
    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 759
    Par défaut
    Salut,

    Citation Envoyé par noureddine1967 Voir le message
    Et voici le message d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    t1 = QThread.thread(name='Création Tables Temporaires1', target=self.creation_tables_tmp1)
    TypeError: thread() takes no keyword arguments
    Le plus bizarre est que çà ne râle pas sur ".thread": une lecture diagonale de la documentation me laisse perplexe quant à son existence.
    Si vous êtes sous Python2, quelle version de Qt/pyQt utilisez vous?

    Pour le reste, l'erreur veut simplement dire que vous n'avez pas ouvert la documentation pour savoir quels paramètres passer à.... Et pour moi, pour jouer avec Qt et les threads, il faut déjà savoir un peu se dépatouiller avec la documentation, les recherches d'exemples sur Internet,...

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 17/02/2017, 21h18
  2. Réponses: 1
    Dernier message: 17/03/2010, 15h33
  3. Réponses: 2
    Dernier message: 14/05/2009, 08h01
  4. hébergement de base de donnée gratuite avec accès par Delphi
    Par dan_lizhot dans le forum Bases de données
    Réponses: 9
    Dernier message: 17/02/2009, 00h40
  5. Accès à une base de données Oracle avec un tunnel ssh
    Par sofiane1111 dans le forum Bases de données
    Réponses: 5
    Dernier message: 14/11/2007, 10h14

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