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

Tkinter Python Discussion :

sqlite3 enregistrement a la fermeture [Python 3.X]


Sujet :

Tkinter Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    Consultant en gestion de la relation client (GRC)
    Inscrit en
    Mars 2024
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Consultant en gestion de la relation client (GRC)

    Informations forums :
    Inscription : Mars 2024
    Messages : 5
    Par défaut sqlite3 enregistrement a la fermeture
    Bonjour,

    J'ai quelque chose de bizarre dans mon script. Il fonctionne très bien mais l'enregistrement dans la bdd ne se fait que lorsque la fenetre tkinter est fermée.
    Auriez-vous une solution pour que l'enregistrement ou la mise à jour se fasse sans devoir fermer la fenetre

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    import sqlite3
    import creation
    import cartouche
    import ajout_supp
    import tkinter
    from pathlib import Path
    import os
     
    cart = cartouche.Cartouches()
     
    def valider_scan(entry_code_barre):
        # recuperation du code barre
        code_barre = entry_code_barre.get()
     
        # vidage de l'entry
        entry_code_barre.delete(0, 'end')
     
        # connexion bdd
        chemin_bdd = Path(str(Path(os.getcwd()).parent)+r"\cartouche.db")
        connection = sqlite3.connect(chemin_bdd)
        curseur = connection.cursor()
     
        # test si le code barre existe
        nb_ligne = curseur.execute("""SELECT COUNT(*) FROM cartouches WHERE code_barre=?""", (code_barre, )).fetchone()[0]
     
        if nb_ligne == 0:
            # s'il n existe pas on ajoute
            creation.creation_cartouche(cart)
     
            curseur.execute("""INSERT INTO cartouches(nom, type, quantite, code_barre) VALUES(?, ?, ?, ?)""", (cart.nom, cart.type, 1, code_barre))
            connection.commit()
        else:
            # si le code barre existe on demande si on ajoute ou en supprime
            ajout_supp.ajout_supp_cartouche(cart)
     
            # recupere le nombre de cartouche
            nb_cartouche = curseur.execute("""SELECT quantite FROM cartouches WHERE code_barre=?""", (code_barre,)).fetchone()[0]   
     
            if cart.ajout == "ajout":
                # on ajoute une cartouche
                nb_cartouche += 1
     
                # on met a jour la valeur dans la bdd
                curseur.execute("""UPDATE cartouches SET quantite=? WHERE code_barre=?""", (nb_cartouche, code_barre))
                connection.commit()
     
            if cart.ajout == "supp":
                # on supprime une cartouche
                nb_cartouche -= 1
     
                # on met a jour la valeur dans la bdd
                curseur.execute("""UPDATE cartouches SET quantite=? WHERE code_barre=?""", (nb_cartouche, code_barre))
                connection.commit()
     
        # fermeture de la bdd
        connection.close()
     
    """
    fenetre principale
    """
    if __name__ == '__main__':
        win_scan = tkinter.Tk()
        win_scan.title("scan des codes barres des cartouches")
        win_scan.geometry("400x100")
     
        label_scan = tkinter.Label(win_scan, text="en attente de scan ...")
        entry_scan = tkinter.Entry(win_scan)
     
        label_scan.pack(padx=10, pady=10)
        entry_scan.pack(padx=10, pady=10)
     
        # permet d'entrer dans le entry
        entry_scan.focus_set()
     
        entry_scan.bind('<Return>',lambda e: valider_scan(entry_scan))
     
        win_scan.mainloop()

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

    Normalement commit suffit. Comment arrivez vous à constater ce que vous racontez ?

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

  3. #3
    Membre à l'essai
    Homme Profil pro
    Consultant en gestion de la relation client (GRC)
    Inscrit en
    Mars 2024
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Consultant en gestion de la relation client (GRC)

    Informations forums :
    Inscription : Mars 2024
    Messages : 5
    Par défaut
    Je suis bien d'accord, c'est pour ça que je trouve cela bizarre.

    Je le constate de 2 facons :
    - j'ai une autre fenetre qui m'affiche ce qui est enregistré dans la bdd
    - avec DB Browser for SQLite

    dans les 2 cas rien n'apparait tant que la fenetre reste ouverte et des la fermeture ca apparait

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Citation Envoyé par olivbarb154892 Voir le message
    dans les 2 cas rien n'apparait tant que la fenetre reste ouverte et des la fermeture ca apparait
    SQLite n'accepte pas ce genre de concurrence: ça attend jusqu'à l'expiration d'un timeout l'accès exclusif au fichier de la base.

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

  5. #5
    Membre à l'essai
    Homme Profil pro
    Consultant en gestion de la relation client (GRC)
    Inscrit en
    Mars 2024
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Consultant en gestion de la relation client (GRC)

    Informations forums :
    Inscription : Mars 2024
    Messages : 5
    Par défaut
    ok pour l'affichage mais dans ce cas pourquoi nb_ligne (ligne 24) reste à 0 et le script me relance creation_cartouche alors que DB Browser for SQLite et ma fenetre d'affichage (affichage.py) sont fermés (je viens de tester) ?

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Citation Envoyé par olivbarb154892 Voir le message
    ok pour l'affichage mais dans ce cas pourquoi nb_ligne (ligne 24) reste à 0
    Voilà un autre sujet qui sans code complet pour le reproduire...
    Tout ce que je peux dire c'est que ces quelques lignes fonctionnent très bien:
    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
    >>> import sqlite3
    >>> con = sqlite3.connect("tutorial.db")
    >>> cur = con.cursor()
    >>> cur.execute("CREATE TABLE movie(title, year, score)")
    <sqlite3.Cursor object at 0x000001B7FDA43740>
    >>> cur.execute("""
    ...     INSERT INTO movie VALUES
    ...         ('Monty Python and the Holy Grail', 1975, 8.2),
    ...         ('And Now for Something Completely Different', 1971, 7.5)
    ... """)
    <sqlite3.Cursor object at 0x000001B7FDA43740>
    >>> con.commit()
    >>> qry = "SELECT COUNT(*) FROM movie WHERE year=?"
    >>> cur.execute(qry, (1975,))
    <sqlite3.Cursor object at 0x000001B7FDA43740>
    >>> _.fetchone()
    (1,)
    >>>

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

  7. #7
    Membre à l'essai
    Homme Profil pro
    Consultant en gestion de la relation client (GRC)
    Inscrit en
    Mars 2024
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Consultant en gestion de la relation client (GRC)

    Informations forums :
    Inscription : Mars 2024
    Messages : 5
    Par défaut
    comme je le disais, mon code fonctionne très bien sauf que je dois fermer la fenetre tkinter pour l'enregistrement dans la bdd. Ce n'est donc pas, je pense, un problème de sqlite

  8. #8
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 322
    Par défaut
    bonjour

    on ne connait pas la structure, apparemment code_barre est un index unique.
    Si oui, la ligne 24 n'a pas à exister sous cette forme.

    - Pour insérer dans ton cas, on utilise normalement "INSERT OR IGNORE INTO cartouches"
    - Pour incrémenter ou décrémenter, on peut utiliser la même requete sql !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    cur.execute(
        """
        UPDATE cartouches 
            SET quantite = quantite + ?
            WHERE code_barre = ?
        """,
        (1 if "ajout" else -1, code_barre)
    )
    EDIT: "SELECT COUNT(*)" clairement pas top !

    Citation Envoyé par olivbarb154892 Voir le message
    je dois fermer la fenetre tkinter pour l'enregistrement dans la bdd. Ce n'est donc pas, je pense, un problème de sqlite
    Sqlite n'est pas fait pour un accès "multiple", donc je ne comprends pas ta question.
    Tu ne confonds pas commit() et close() ? c'est close() qui va écrire dans le fichier. sqlite charge la base de donnée en mémoire et donc les "commits" sont faits par défaut en mémoire.
    Si tu désires avoir un accès en temps réel depuis plusieurs applications, alors il faut t'orienter vers un serveur de DB.

    ps: tous ceci n'a rien à voir avec python (pas le bon forum)

  9. #9
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Citation Envoyé par olivbarb154892 Voir le message
    Ce n'est donc pas, je pense, un problème de sqlite
    Le problème est dans votre code (ou dans vos attentes si ce n'est les 2).
    Et il ne faut pas "penser" mais arriver à reproduire ce que vous constatez pour espérer le comprendre et le corriger.
    A vous de voir.

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

  10. #10
    Membre à l'essai
    Homme Profil pro
    Consultant en gestion de la relation client (GRC)
    Inscrit en
    Mars 2024
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Consultant en gestion de la relation client (GRC)

    Informations forums :
    Inscription : Mars 2024
    Messages : 5
    Par défaut
    Citation Envoyé par papajoker Voir le message
    bonjour

    on ne connait pas la structure, apparemment code_barre est un index unique.
    Effectivement, code_barre est une suite de chiffres ou de lettres

    Citation Envoyé par papajoker Voir le message
    EDIT: "SELECT COUNT(*)" clairement pas top !
    Dans ce cas comment savoir si la code_barre ou une autre valeur a déjà été enregistrée dans la bdd ?

    Citation Envoyé par papajoker Voir le message
    Tu ne confonds pas commit() et close() ? c'est close() qui va écrire dans le fichier. sqlite charge la base de donnée en mémoire et donc les "commits" sont faits par défaut en mémoire.
    A la fin de ma fonction il y a bien un close()

    Je n'ai peut-être pas été très clair. Ce que je veux, c'est :
    - executer le script que j'ai mis ci-dessus
    - Je scanne un code barre
    - la fonction vérifie si le code barre existe déjà ou non dans la bdd
    - s'il existe il execute la fonction pour ajouter ou supprimer la quantité de 1
    - s'il n'existe pas il ajoute le code barre dans la bdd.

    Je veux du temps réél mais pas depuis plusieurs applications.

    Citation Envoyé par papajoker Voir le message
    - Pour incrémenter ou décrémenter, on peut utiliser la même requete sql !
    Merci pour le bout de code qui me permet de supprimer quelques lignes

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

    Vous êtes têtu? Votre code pourrait sans doute être mieux écrit mais rien n'explique ce que vous constatez... et comme on ne peut pas reproduire, difficile d'en dire plus.

    Je peux faire marcher votre code (en le modifiant);
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    import sqlite3
    #import creation
    # import cartouche
    # import ajout_supp
    import tkinter
    from pathlib import Path
    import os
     
    #cart = cartouche.Cartouches()
     
    def valider_scan(entry_code_barre):
        # recuperation du code barre
        code_barre = entry_code_barre.get()
     
        # vidage de l'entry
        entry_code_barre.delete(0, 'end')
     
        # connexion bdd
        chemin_bdd = "cartouche.db"
        connection = sqlite3.connect(chemin_bdd)
        curseur = connection.cursor()
     
        # test si le code barre existe
        nb_ligne = curseur.execute("""SELECT COUNT(*) FROM cartouches WHERE code_barre=?""", (code_barre, )).fetchone()[0]
        print(f'{nb_ligne=}')
        if nb_ligne == 0:
            # # s'il n existe pas on ajoute
            # creation.creation_cartouche(cart)
     
            curseur.execute("""INSERT INTO cartouches(nom, type, quantite, code_barre) VALUES(?, ?, ?, ?)""", ('nom', 'type', 1, code_barre))
            connection.commit()
        else:
            # si le code barre existe on demande si on ajoute ou en supprime
            #ajout_supp.ajout_supp_cartouche(cart)
     
            # recupere le nombre de cartouche
            row = curseur.execute("""SELECT * FROM cartouches WHERE code_barre=?""", (code_barre,)).fetchone()
            print(f'{row}')
     
            nb_cartouche = curseur.execute("""SELECT quantite FROM cartouches WHERE code_barre=?""", (code_barre,)).fetchone()[0]   
     
            # if cart.ajout == "ajout":
            #     # on ajoute une cartouche
            nb_cartouche += 1
     
                # on met a jour la valeur dans la bdd
            curseur.execute("""UPDATE cartouches SET quantite=? WHERE code_barre=?""", (nb_cartouche, code_barre))
            connection.commit()
     
            # if cart.ajout == "supp":
            #     # on supprime une cartouche
            #     nb_cartouche -= 1
     
            #     # on met a jour la valeur dans la bdd
            #     curseur.execute("""UPDATE cartouches SET quantite=? WHERE code_barre=?""", (nb_cartouche, code_barre))
            #     connection.commit()
     
        # fermeture de la bdd
        connection.close()
     
    """
    fenetre principale
    """
    if __name__ == '__main__':
     
        chemin_bdd = "cartouche.db"
        if not os.path.exists(chemin_bdd):
           with sqlite3.connect(chemin_bdd) as c:
               c.execute('CREATE TABLE cartouches(nom, type, quantite, code_barre)')
     
        win_scan = tkinter.Tk()
        win_scan.title("scan des codes barres des cartouches")
        win_scan.geometry("400x100")
     
        label_scan = tkinter.Label(win_scan, text="en attente de scan ...")
        entry_scan = tkinter.Entry(win_scan)
     
        label_scan.pack(padx=10, pady=10)
        entry_scan.pack(padx=10, pady=10)
     
        # permet d'entrer dans le entry
        entry_scan.focus_set()
     
        entry_scan.bind('<Return>',lambda e: valider_scan(entry_scan))
     
        win_scan.mainloop()
    Et je peux constater que valider le même code barre incrémente bien le nombre de cartouches (et je peux le lire via un autre programme lancé pendant que le GUI attend).

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

  12. #12
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 322
    Par défaut
    Comme dit plus, ici tu n'as que des problèmes sql. Il faut donc voir plutôt sur le forum sql.

    Puisque tu ne connais pas, tu fais un code python bancal pour palier tes manques.
    Tu n'as même pas répondu à la question basique de la stucture !

    comment savoir si la code_barre ou une autre valeur a déjà été enregistrée
    Existe "INSERT OR" donc il n'y a même pas à écrire le moindre code python !
    Il faut déjà lire la doc sql et tester sans python

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE TABLE IF NOT EXISTS machin (
        code text primary key UNIQUE,
        label text,
        count integer
    );
    INSERT or IGNORE INTO machin VALUES ("A1", 'A faire', 1);
    INSERT or IGNORE INTO machin VALUES ( "B2", 'Ne pas oublier', 1);
    /* ignoré sans erreur */
    INSERT or IGNORE INTO machin VALUES ( "B2", "un nouveau ?", 0);
    /* et dans ton cas particulier */
    /* insert(si nouveau) et incrément dans la foulée, puisque maintenant le code barre existe certainement */
    INSERT or IGNORE INTO machin VALUES ( "C32", "nouveau si existe pas", 0);
    UPDATE machin SET count = count +1 WHERE code="C32";
    ps: marche car le code bar est marqué UNIQUE

    EDIT: "SELECT COUNT(*)" clairement pas top !
    Ici, il fallait comprendre que c'est l'étoile qui me dérange


    ------------
    Au final, on peut avoir une function python du type
    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
    def update(produit: dict, ajout = True):  # retourne le dico mis à jour
        cursor.execute(
            """
            INSERT or IGNORE INTO machin VALUES ( :code, :label, :count);
            """,
            produit
        )
        cursor.execute(
            """
            UPDATE machin SET count = count + ? WHERE code= ?
            """,
            (1 if ajout else -1, produit["code"])
        )
        conn.commit()
        row = cursor.execute("SELECT * FROM machin WHERE code = ?", (produit["code"],))
        return dict(zip([c[0] for c in cursor.description], row.fetchone()))
     
    ...
     
    produit = cartouches.get(
        entry_code_barre.get(),
        {"code": entry_code_barre.get(), "label": "nouveau", "count":0 }
    )     # ? dans le genre
    produit = update(produit, True)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Enregistrement a la fermeture
    Par DavidGagnaire dans le forum VBA Access
    Réponses: 2
    Dernier message: 24/06/2011, 16h15
  2. Réponses: 11
    Dernier message: 06/04/2011, 15h12
  3. [XL-2003] enregistrer a la fermeture
    Par olivier-tig dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 08/09/2009, 16h23
  4. Réponses: 3
    Dernier message: 13/01/2009, 12h03
  5. Réponses: 6
    Dernier message: 07/08/2007, 17h01

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