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 :

Application multi utilisateur


Sujet :

PyQt Python

  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut Application multi utilisateur
    Bonjour,
    j'ai une petite application qui permet de gérer une base de donnée.

    Cette base de donnée apparait via un QTableWidget et est alimentée par un dataframe (pandas) enregistré en dur sous un csv.
    Cette dataframe est instanciée lors de l'ouverture de l'application et c'est à partir de cette instance que j'appelle le "to_csv()" de pandas à chaque évènement de modif de la QTableWidget (ou plutôt de la modification de ses items).

    jusque là, pas de souci, tout marche bien! (enfin tant que je suis seul à utiliser l'interface)

    Si différents utilisateurs ouvre l'application, il se trouve que l'instance initiale de ma base de donnees est gérée indépendamment pour chaque utilisateur.
    Du coup, je me retrouve avec 2 applications qui viennent "écraser" successivement chaque nouvelle versions en ignorant les modifs des autres utilisateurs.

    Pour solutionner cela, je me suis dit qu'il fallait que je n'instancie pas une seule fois ma dataframe mais que je l'instancie à chaque modif de mon QTableWidget. Comme cela, à chaque modif de chaque utilisateur le to_csv() associé à la modif implique que n'importe quel autre utilisateur qui modifie quelque chose depuis son application ré-ouvre le csv le plus récent...
    spontanément je ne l'avais pas fait parce que je trouvais ça lourd... et pas élégant.

    actuellement, j'ai positionné ce bout de code dès le début de la fonction appelée lors d'une modification d'un de mes items (contenu dans ma QTable Widget):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            with open(str(self.instance_dt.nom_fichier_bdd) + str(".csv"), newline='', encoding="utf-8-sig") as csvfile:
                self.ui.dataframe_from_csv = pd.DataFrame(csv.reader(csvfile, delimiter=';'))
                self.ui.dataframe_from_csv.columns = self.ui.dataframe_from_csv.iloc[0]
                self.ui.dataframe_from_csv = self.ui.dataframe_from_csv.drop(0)
                self.ui.dataframe_from_csv = self.ui.dataframe_from_csv.sort_values(by=["N°DT"])
    Mais j'ai l'impression que cela reste maladroit...

    est-ce que cette approche d'utiliser un with open à chaque fois qu'une modif est faite se pratique? est-ce viable?
    comment sont gérées les bases de données ou différents utilisateurs peuvent modifier en même temps les données contenues?

    merci,
    cordialement,
    clem

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

    Citation Envoyé par clement_74 Voir le message
    comment sont gérées les bases de données ou différents utilisateurs peuvent modifier en même temps les données contenues?
    Ce que vous appelez base de données est juste un fichier texte partagé où il faudrait inventer une politique pour que ce soit gérable.
    Les vraies bases de données ont été inventées pour résoudre çà... mais il faut savoir que ça existe et comment les utiliser.

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

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par clement_74 Voir le message
    j'ai une petite application qui permet de gérer une base de donnée.

    Cette base de donnée apparait via un QTableWidget et est alimentée par un dataframe (pandas) enregistré en dur sous un csv.
    Appellation "base de données" un peu riche pour un simple CSV...

    Citation Envoyé par clement_74 Voir le message
    Si différents utilisateurs ouvre l'application, il se trouve que l'instance initiale de ma base de donnees est gérée indépendamment pour chaque utilisateur.
    Du coup, je me retrouve avec 2 applications qui viennent "écraser" successivement chaque nouvelle versions en ignorant les modifs des autres utilisateurs.
    Bienvenue dans le monde passionnant des accès concurrents. Tu peux reproduire ce comportement en ouvrant deux fois ton CSV via notepad++

    Citation Envoyé par clement_74 Voir le message
    est-ce que cette approche d'utiliser un with open à chaque fois qu'une modif est faite se pratique? est-ce viable?
    Pas vraiment (risque toujours possible que deux opérations se fassent "au même moment" et donc le second écrase le premier). Pire, la gestion OS peut tomber en carafe à ce moment là et tu te retrouves avec un fichier vide.
    Le minimum pour éviter cela est de rajouter un système de lock. Si deux opérations parallèles arrivent, la seconde attend que la première ait finie.

    Citation Envoyé par clement_74 Voir le message
    comment sont gérées les bases de données ou différents utilisateurs peuvent modifier en même temps les données contenues?
    Les vraies bdd passent par ce qu'on appelle un "moteur", un programme qui prend en charge toutes les requêtes. C'est pour cela qu'il faut passer par une "connexion bdd", c'est à dire une demande au moteur de te donner une ligne de communication pour lui transmettre tes ordres. De là il peut les gérer et les appliquer de façon séquentielle et non concurrentielle (même si de ton côté tu crois que c'est le cas).
    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 confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut
    Bonjour,
    merci pour vos réponses,
    j'ai opté pour convertir la gestion de mon csv initial avec un fichier .db via sqlite3
    pour l'instant j'arrive à m'en sortir... pas complétement fini de tout "relier" mais ça me parait prometteur!
    (heureux que pandas et sqlite fonctionnent bien ensemble :-))

    merci!

  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
    Bonjour,

    Je ne suis pas sûr d'avoir bien compris le projet, mais s'il s'agit de permettre l'accès à la base de données à plusieurs utilisateurs en même temps, il y a un os: sqlite3 n'a pas cette capacité. J'aime bien sqlite3, mais il est normalement lié à un seul programme.

    Il faudrait plutôt utiliser un serveur, et prendre un SGBD comme mysql ou postgresql. Chaque utilisateur pourra communiquer avec le SGBD par requêtes SQL (lecture, modifs, ...) comme pour sqlite3, mais avec l'avantage que la résolution des accès multi-utilisateurs fait déjà partie du système.

  6. #6
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut
    Bonjour,
    Je reviens sur le sujet après l'avoir mis de côté quelques temps...
    Pour préciser le contexte/objectif, ci dessous quelques précisions:

    - j'aimerais sécuriser la gestion d'un fichier contenant de la data vis à vis de possibles utilisations simultanées (par des utilisateurs différents).
    - le fichier en question doit rester sur un réseau commun (non internet).
    - Chaque utilisateur doit pouvoir y accéder via son propre PC (en accès libre sans mot de passe ou identification particulière)
    - TOUS les utilisateur ne disposent pas de python sur leur PC (ils lancent l'appli via un .exe généré avec cx_freeze).
    - la data n'a rien de "lourd" à gérer, c'est un fichier qui contient max 5000 lignes pour 20 à 25 colonnes.
    - Pas vraiment besoin de gérer la cohérence des données (le R de SGBDR m'importe peu). En gros je veux juste pouvoir stacker de la data.
    - en termes de "flux" d'utilisateurs, je ne vise pas la centaine d'utilisateurs simultanés... bien moins.

    La gestion de ce fichier avec pandas (dataframe) + csv suffirait largement en termes de fonctionnalités => Le seul hic (et c'est un gros hic) c'est l'aspect accès concurrent.

    Pour l'instant l'utilisation d'un accès concurrent ne m'a jamais trop posé de problèmes graves.
    Mais j'ai le pressentiment que ce n'est qu'une question de temps...
    Alors j'aimerais basculer sur une approche plus robuste.

    de ce que je comprend il faut que j'opte pour un "SGBD" en évitant sqlite3 puisqu'il ne gère pas le multithreading.
    compte tenu de l'aspect peut être un peu "simpliste" de mon besoin n'y a-t-il pas plus "léger" que de partir sur du mysql? (je n'en ai jamais fait alors ça me parait "chamboulant"... Donc avant de me lancer dedans j'aimerais juste être sure que c'est vraiment ce dont j'ai besoin.

    merci pour vos conseils :-)

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    Donc avant de me lancer dedans j'aimerais juste être sure que c'est vraiment ce dont j'ai besoin.
    La base de données est une solution générique pour traiter ce genre de problème.
    Est ce qu'on peut faire sans? Probablement, mais c'est la conception qui est à (re)voir en se posant des questions sur la nature des accès concurrents et comment y pallier.

    La gestion de ressources partagées est du domaine de l'environnement système...
    Si une solution technique existe, la programmer avec Python (ou un autre langage ne pose pas de soucis particulier).
    note: une usine à gaz comme sharepoint sait faire çà (avec ou sans base de données derrière, l'important étant le "service" rendu à l'utilisateur et au programmeur via des API disponibles.

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

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    - j'aimerais sécuriser la gestion d'un fichier contenant de la data vis à vis de possibles utilisations simultanées (par des utilisateurs différents).
    Voilà ce qui va se passer. Prenons un fichier qui contient "toto", et deux utilisateurs X et Y
    • X et Y lisent le fichier et mettent leur contenu en mémoire (fatalement). Chacun d'eux contient "toto"
    • X modifie et met "tata". Y continue à avoir "toto". Tu peux rajouter un système via QTimer pour que le fichier soit automatiquement rechargé à intervalles réguliers, c'est pas super compliqué, mais durant l'intervalle l'utilisateur Y n'a quand-même pas l'info
    • X et Y modifient en même temps, X met "tata" et Y met "tutu", c'est le dernier qui écrit qui gagne (tu connais le cas car tu l'as déjà eu). La solution serait de rajouter un système de lock. Le premier qui "prend" le lock gagne le fichier. il le traite, fait ses modifs, le sauvegarde et par là même "rend" le lock. Le fichier est alors disponible pour qui en a envie. C'est faisable, Office le fait quand il te dit que le fichier que tu veux ouvrir est déjà utilisé par l'autre abruti qui est parti en réunion sans le libérer. Mais je viens de te résumer un des soucis inhérents à cette techno.

    Le reste de tes contraintes est négligeable. Réseau commun ou internet c'est la même technologie, pas de mot de passe c'est aussi bien ça évite de devoir rajouter une gestion des mots de passe et de ses changements, que Python soit installé ou englobé dans un exécutable ça reste Python (tout comme on peut créer une archive zip seule ou une archive englobant les outils pour la décompresser), et le fait que ce ne soit pas "lourd" en terme de datas ou d'utilisateurs n'empêche pas ces soucis.

    Malheureusement même si tu considères tes soucis faibles, ils le sont assez pour mériter un SGBD. C'est un peu comme celui qui dit "j'ai acheté une barque, mais j'aimerais maintenant me promener le jour, la nuit, et pouvoir la ranger quand je n'en ai plus besoin". On lui répondra "il faut un port pour la ranger, et un phare pour trouver le port la nuit". Il répondra "oh, c'est pas un paquebot, c'est une barque" mais cela ne change rien, il faut quand-même un port et un phare. Ensuite, avec le port et le phare on pourra faire venir des paquebots si on veut. Pour toi c'est pareil. Un SGBD (et perso j'ai une préférence pour Postgres qui est full gratuit, mysql n'est gratuit que pour le minimum) il faut un serveur, il faut l'administrer, il faut programmer des sauvegardes de la bdd, ok c'est du travail. Mais une fois qu'il y est, il est disponible pour n'imprte qui qui veut monter son appli.
    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]

  9. #9
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut
    Bonjour,
    merci pour pour les retours! je pense que je vais sérieusement considérer la gestion de lock :-)

    juste pour ma culture, j'avais écrit le bout de code ci-dessous avant d'écarter sqlite3 de la possible solution (puisqu'apparemment il ne gère pas le multi utilisateurs).
    à l'époque (et encore aujourd'hui) ça donne pourtant l'impression que ça pouvait marcher.
    j'avais rapidement testé avec un collègue pour voir si on s'écrasait nos datas respectives...

    Ci-dessous, on se connecte au fichier .db au moment ou la fenetre s'ouvre. A chaque "clic" sur le bouton, on ajoute une ligne et on sauvegarde la database via commit().
    Même en gardant chacune des interfaces ouvertes sur 2 PC différetns les ajouts successifs s'affichent et s'empilent correctement...

    avaient-on eu juste de la chance? Ou qu'est-ce qui m'échappe?

    merci:

    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
    from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QMessageBox
    import sys
    import sqlite3
    import os
     
    class Bouton_simple(QPushButton):
        def __init__(self, ui, texte):
            super().__init__()
            self.setStyleSheet("""QPushButton{font: 24px}""")
            self.setText(texte)
     
    class Fenetre_Principale(QMainWindow):
        def __init__(self):
            QMainWindow.__init__(self)
            self.fenetre_widget = QWidget()
            self.modif = Bouton_simple(self, texte="ajouter")
     
            self.layout_vertical_global = QVBoxLayout()    
            self.layout_vertical_global.addWidget(self.modif)
     
            self.fenetre_widget.setLayout(self.layout_vertical_global)      
            self.setCentralWidget(self.fenetre_widget)
     
            self.modif.clicked.connect(lambda: self.add_line())
            self.resize(800, 600)
     
            self.connection = sqlite3.connect('pythonsqlite.db')
            self.cursor = self.connection.cursor()
     
            self.index = 0
            self.name = os.getenv("LS_USER_FULLNAME")
     
            self.show()
     
     
        def add_line(self):
     
            self.index = self.index + 1
            data = (str(self.index), self.name, '3', "4", "5")
            sql_add_query = """INSERT INTO projects VALUES""" + str(data)
     
            try:
                self.connection.execute(sql_add_query)
                self.connection.commit()
                full_row = ""
                for row in self.cursor.execute("SELECT * FROM projects;"):
                    full_row = full_row + str(row) + "\n"
     
                QMessageBox.information(QWidget(), "etat BD", str(full_row))
            except:
                self.cursor.close()
                QMessageBox.information(QWidget(), "KO") 
     
     
    if __name__ == "__main__":
        appli = QApplication(sys.argv)
        fenetre_main = Fenetre_Principale()
        sys.exit(appli.exec_())

  10. #10
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    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 323
    Par défaut
    bonjour
    Citation Envoyé par clement_74 Voir le message
    Même en gardant chacune des interfaces ouvertes sur 2 PC différents les ajouts successifs s'affichent et s'empilent correctement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            self.connection = sqlite3.connect('pythonsqlite.db')
    Ici, tu charges un fichier en local Pour partager, il faudrait au minimum charger ce fichier commun depuis un serveur
    ps: existe un système de "lock" avec sqlite

    Ton besoin a l'air d'être pour un intranet avec "moins de 100 personnes" donc il ne serait pas étonnant qu'il existe déjà un serveur d'installé ? il existe des dizaines de solutions, et vu ton besoin (une seule table ici?), tu n'as pas un besoin impératif de sql, un serveur nosql devrait aussi faire l'affaire

  11. #11
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    merci pour pour les retours! je pense que je vais sérieusement considérer la gestion de lock
    Les verrous sont une fonctionnalité "locale" a un système... Faire ça en distribué ne se fait pas sur un coin de table. La base de donnée s'en sort car les mises à jours demandées sont effectuées séquentiellement par le serveur (pas par les clients directement).
    Ce dernier pourra lui utiliser les verrous de l'environnement système.

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

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    juste pour ma culture, j'avais écrit le bout de code ci-dessous avant d'écarter sqlite3 de la possible solution (puisqu'apparemment il ne gère pas le multi utilisateurs).
    à l'époque (et encore aujourd'hui) ça donne pourtant l'impression que ça pouvait marcher.
    Il y a quelques erreurs
    • faut remplacer self.modif.clicked.connect(lambda: self.add_line()) par self.modif.clicked.connect(self.add_line) (ben oui, au lieu de passer une fonction lambda qui appellera add_line quand elle sera exécutée on passe directement add_line qui sera alors exécutée directement)
    • le parent de tes QMessageBox ne doit pas être un QWidget() créé dans le vide mais self.fenetre_widget qui est un widget existant. Accessoirement un QMainWindow doit posséder un widget central qui définira son comportement => https://pyqt.developpez.com/telechar...-au-mainwindow et dans ce cas on peut utiliser ce widget comme parent des autres widgets créés
    • un QMessageBox doit avoir 4 paramètres (le parent, le titre, le message et le bouton mais lui il peut être ignoré). Mais ton dernier QMessageBox n'en a que 2. Donc si tu lui rajoutes en 3° paramètre la string expliquant l'exception, on saura pourquoi ça plante (par exemple chez-moi ton code plante parce que ma bdd ne contient pas de table "project", il faudrait que tu nous donnes le script de création de la bdd pour que je puisse tester)


    Citation Envoyé par papajoker Voir le message
    et vu ton besoin (une seule table ici?), tu n'as pas un besoin impératif de sql, un serveur nosql devrait aussi faire l'affaire
    Bien vu (j'y pense jamais)
    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]

  13. #13
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut
    pour l'idée du lock c'est bien le lock du module threading qui est proposé?

    l'idée serait de basculer l'ensemble de la fonction de mise à jour dans un thread, de vérouiller la base de donnée en entrée de fonction et de la déverouiller en sortie?

    en cas de sollicitation de la fonction sur un état verrouiller ajouter un timer pour refaire une ou deux tentative quelques ms plus tard et si re-échec simplement indiquer que le fichier n'est pas disponible?

  14. #14
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    l'idée serait de basculer l'ensemble de la fonction de mise à jour dans un thread, de vérouiller la base de donnée en entrée de fonction et de la déverouiller en sortie?
    Non, ça ne règle pas le cas des deux users qui ont lu "toto" en même temps. Le premier écrit "titi", ok il peut écrire mais l'autre, quand il prend le lock, écrit alors "tutu" et écrase "titi".
    Faut prendre le lock dès la lecture...
    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]

  15. #15
    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

    Quand je disais que sqlite3 ne supporte pas le multi-utilisateurs, c'est en supposant que chaque utilisateur pouvait accéder à n'importe quel moment, y compris en même temps qu'un autre utilisateur. Mais plusieurs programmes et plusieurs utilisateurs peuvent accéder à la même base de données sqlite3, à condition que ce ne soit pas au même moment.

    Il m'est ainsi arrivé d'utiliser la même base sqlite3 avec le pilote de PyQt5 pour les graphiques (QTableView par exemple), puis à un autre moment avec le pilote de Python (celui-ci ayant les avantages de pouvoir ajouter des fonctions python utilisables en SQL). Avec une ouverture et une fermeture à chaque accès. Cela ne pose aucun problème.

    Au cas où on ne respecte pas cette contrainte, il serait préférable que le programme alerte, voire plante, parce que à défaut, on risque des défauts d'intégrité de la base de données (surtout avec les transactions), que l'on ne verra pas forcément tout de suite...

  16. #16
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    pour l'idée du lock c'est bien le lock du module threading qui est proposé?
    Si les clients/utilisateurs sont sur des machines différentes, il n'est pas prévu pour (et ça ne marchera pas).

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

  17. #17
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut
    "il faudrait que tu nous donnes le script de création de la bdd pour que je puisse tester)"


    ci dessous le code avec les corrections (merci) et la possibilité de le faire tourner ce bout de code sans prérequis sur lePC (en créant d'office un fichier et sa table).

    sinon, à la leture de l'ensemble des messages, j'avoue être un peu perdu quant à l'orientation que je doit finalement prendre: lock pas lock? noSQL ou mySQL? vraiment pas sqlite3 du coup?

    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
    from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QMessageBox
    import sys
    import sqlite3
    import os
     
    class Bouton_simple(QPushButton):
        def __init__(self, ui, texte):
            super().__init__()
            self.setStyleSheet("""QPushButton{font: 24px}""")
            self.setText(texte)
     
    class Fenetre_Principale(QMainWindow):
        def __init__(self):
            QMainWindow.__init__(self)
            self.fenetre_widget = QWidget()
            self.modif = Bouton_simple(self, texte="ajouter")
     
            self.layout_vertical_global = QVBoxLayout()    
            self.layout_vertical_global.addWidget(self.modif)
     
            self.fenetre_widget.setLayout(self.layout_vertical_global)      
            self.setCentralWidget(self.fenetre_widget)
     
            self.modif.clicked.connect(self.add_line)
            self.resize(800, 600)
     
            self.connection = sqlite3.connect('Test_pour_Forum.db')
            self.cursor = self.connection.cursor()
     
            self.cursor.execute("""CREATE TABLE IF NOT EXISTS projects
                                ([Col1] TEXT, [Col2] TEXT, [Col3] TEXT, [Col4] TEXT, [Col5] TEXT)""")
     
            self.index = 0
            self.name = os.getenv("LS_USER_FULLNAME")
     
            self.show()
     
     
        def add_line(self):
     
            self.index = self.index + 1
            data = (str(self.index), self.name, '3', "4", "5")
            sql_add_query = """INSERT INTO projects VALUES""" + str(data)
     
            try:
                self.connection.execute(sql_add_query)
                self.connection.commit()
                full_row = ""
                for row in self.cursor.execute("SELECT * FROM projects;"):
                    full_row = full_row + str(row) + "\n"
     
                QMessageBox.information(self.fenetre_widget, "etat BD", str(full_row))
            except Exception as erreur:
                self.cursor.close()
                QMessageBox.information(self.fenetre_widget, "KO", str(erreur))
     
     
    if __name__ == "__main__":
        appli = QApplication(sys.argv)
        fenetre_main = Fenetre_Principale()
        sys.exit(appli.exec_())

  18. #18
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    sinon, à la leture de l'ensemble des messages, j'avoue être un peu perdu quant à l'orientation que je doit finalement prendre: lock pas lock? noSQL ou mySQL? vraiment pas sqlite3 du coup?
    Une vraie base de donnée SQL multi-utilisateurs suffira.
    NoSQL est surdimensionné pour une aussi petite base de données (un SGDB SQL aussi).

    sqlite3 pourrait le faire avec un serveur au dessus pour gérer les accès concurrents... à condition que le code à ajouter dans le serveur ne soit pas trop "compliqué" (sinon autant prendre un SGDB prêt à l'emploi).

    Ce qui dépend des requêtes à sérialiser maintenant et dans le futur de l'application et le retour à l'étape "conception".

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

  19. #19
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    ci dessous le code avec les corrections (merci) et la possibilité de le faire tourner ce bout de code sans prérequis sur lePC (en créant d'office un fichier et sa table).
    Ok, j'ai pu le faire tourner et donc voir ce qu'il faisait pour le corriger selon ma façon de voir (notamment en rajoutant getpid() dans la data écrite ce qui permet de voir qui écrit, mais ne fonctionne que sous Linux)

    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
    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
    #!/usr/bin/env python3
    from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QMessageBox
    import sys
    import sqlite3
    import os
     
    class Bouton_simple(QPushButton):
    	def __init__(self, ui, texte):
    		super().__init__()
    		self.setStyleSheet("""QPushButton{font: 24px}""")
    		self.setText(texte)
    	# __init__()
    # Bouton_simple
     
    class Fenetre_Principale(QMainWindow):
    	def __init__(self):
    		super().__init__()
    		self.setCentralWidget(QWidget())
    		self.modif = Bouton_simple(self, texte="ajouter")
     
    		self.layout_vertical_global = QVBoxLayout()	
    		self.layout_vertical_global.addWidget(self.modif)
     
    		self.centralWidget().setLayout(self.layout_vertical_global)	  
     
    		self.modif.clicked.connect(self.add_line)
    		self.resize(800, 600)
     
    		self.connection = sqlite3.connect('Test_pour_Forum.db')
    		self.cursor = self.connection.cursor()
     
    		self.cursor.execute("""CREATE TABLE IF NOT EXISTS projects
                                                            ([Col1] TEXT, [Col2] TEXT)""")
     
    		self.index = 0
     
    		self.show()
    	# __init__()
     
    	def add_line(self):
    		name = "%s %d" % (os.getenv("USER"), os.getpid())
     
    		self.index = self.index + 1
    		data = (str(self.index), name)
    		sql_add_query = """INSERT INTO projects VALUES""" + str(data)
     
    		try:
    			self.connection.execute(sql_add_query)
    			self.connection.commit()
    		except Exception as erreur:
    			self.cursor.close()
    			print(erreur)
    			QMessageBox.information(self.centralWidget(), sql_add_query, str(erreur))
    		else:
    			try:
    				full_row = ""
    				for row in self.cursor.execute("SELECT * FROM projects;"):
    					full_row = full_row + str(row) + "\n"
     
    				QMessageBox.information(self.centralWidget(), "etat BD", str(full_row))
    			except Exception as erreur:
    				self.cursor.close()
    				print(erreur)
    				QMessageBox.information(self.centralWidget(), "KO2", str(erreur))
    			# try
    		# try
    	# add_line()
    # Fenetre_Principale
     
    if __name__ == "__main__":
    	appli = QApplication(sys.argv)
    	fenetre_main = Fenetre_Principale()
    	sys.exit(appli.exec_())
    Alors pourquoi ça marche ? Parce que tu ne fais qu'insérer des valeurs calculées. Et sqlite sait parfaitement gérer un insert (ou même plusieurs). Cela n'est pas la même chose que lire de la data, la traiter et réécrire la data modifiée en environnement multiuser. Donc malheureusement ce test n'est pas un "proof of concept"...

    Citation Envoyé par clement_74 Voir le message
    sinon, à la leture de l'ensemble des messages, j'avoue être un peu perdu quant à l'orientation que je doit finalement prendre: lock pas lock? noSQL ou mySQL? vraiment pas sqlite3 du coup?
    C'est vrai, c'est un peu fouilli. Mais déjà les locks j'en ai parlé avant que tu précises que tu étais en réseau. Bon c'était peut-être induit par le terme "multiusers" dans ton esprit mais il existe des systèmes multiusers sur une même machine.
    Ceci dit, tu peux "bidouiller" un système de lock via un fichier créé sur un dossier partagé. Celui qui veut le lock crée le fichier, un autre le veut malheureusement le fichier existe déjà. Mais ça reste de la bidouille et c'est dommage alors qu'il existe des solutions qui ok demandent un peu d'investissement mais qui déjà font le job et surtout (enfin ça dépend de ce que tu fais ensuite) peuvent te le rendre au centuple. Mais ok ça reste un pari (installer un serveur pour une seule appli...). Toutefois j'ai un peu confiance, la nature a horreur du vide. A mon avis, tu installes un serveur SQL, je pense que dans 3 mois il sera blindé par tous les parasites qui viendront te quémander une place. Ou alors la solution serveur nosql de papajoker (je ne connais pas mais si ça porte le nom de "serveur" alors le truc il doit gérer nativement les accès concurrents).
    Malheureusement la solution "fichier simplex" ne pourra pas fonctionner en accès concurrents ou alors au prix comme je l'ai dit de grosses bidouilles à base de dossier partagés comme seul Windows sait faire...
    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]

  20. #20
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut
    Bonjour,
    merci pour tout (j'ai bien aimé l'histoire de la barque et son port)!
    Je part donc sur une install d'un serveur pour m'orienter sur une modif du code pour jouer avec mysql.
    (en espérant que les admin de mon réseau seront ok)

    Sinon, l'idée du lock me plait bien et ce sera mieux le temps de faire la modif embarquant mysql.
    il y a à priori plusieurs voies pour locker un fichier... j'ai sélectionné la bibliothèque filelock... bon choix ou il y a mieux?

    ci dessous la fonction... à priori ça marche (les appels lock.is_locked fonctionnent en confirmant les état bloqués à Flase=>True=>False) mais les appels de os.access n'indiquent pas la même chose... normal? je n'ai pas de deuxième ordi chez moi pour essayer "en vrai" cette fonction sur le réseau avec une config réelle d'accès concurrent...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from filelock import FileLock, Timeout
    import os
    import time
    import random
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        def lock_test(self):
            try:
                debut=time.time()
                lock = FileLock("essai.txt.lock", timeout = 1)             
                print(lock.is_locked, os.access(path = "essai.txt", mode = os.W_OK))
                with lock:
                    print(lock.is_locked, os.access(path = "essai.txt", mode = os.W_OK))
                    with open("essai.txt", "a") as f:
                        f.write(str(int(random.random()*10)) + " " + str(self.name) + " " + str(time.time()) + "\n")
                lock.release()
                print(lock.is_locked, os.access(path = "essai.txt", mode = os.W_OK))
                print(time.time() - debut)
            except Exception as erreur:
                print(erreur)

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/09/2008, 12h26
  2. Application multi utilisateurs
    Par papy75 dans le forum VBA Access
    Réponses: 2
    Dernier message: 24/04/2008, 07h42
  3. Application multi-utilisateur + lock
    Par Ruddy dans le forum ASP.NET
    Réponses: 9
    Dernier message: 17/12/2007, 11h22
  4. [ASP.net & VB.net] Application multi-utilisateur
    Par miya dans le forum ASP.NET
    Réponses: 4
    Dernier message: 03/04/2007, 16h48
  5. [sql server 2000] application multi utilisateur
    Par miya dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/04/2007, 20h43

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