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 :

Probleme de retour avec les fonctions


Sujet :

Tkinter Python

  1. #1
    Membre actif
    Avatar de yorukaze
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    285
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 285
    Points : 299
    Points
    299
    Par défaut Probleme de retour avec les fonctions
    salut salut !

    Je suis en train d'avancer un peu mon lecteur de mail gmail. La principal fonction de ce programme pour l'instant c'est simplement de se connecter avec son adresse et d'avoir la liste de ses mails. D'autres fonctions pour ecrire supprmer etc. des mails viendront par la suite:
    Voila mon code
    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
    import libgmail
    from Tkinter import *
     
    global entreeLogin 
    global entreeMdp
     
     
    def afficherMessage(dossier):
    	can= Canvas(width=500, height=500, bg='white').grid(row=3, column=1)
    	print dossier
     
    def connection(entreeLogin, entreeMdp):
    	global dossier
    	connect = libgmail.GmailAccount(entreeLogin,entreeMdp)
    	connect.login()
    	dossier = connect.getMessagesByFolder('inbox')
    	return dossier
     
    def quitter():
    	fenetre.quit()
     
    #programme principal
     
    fenetre = Tk()
    fenetre.title('Client Gmail')
     
    txtLogin = Label(fenetre, text="Login : ").grid(row=1,column=1)
    entreeLogin = Entry(fenetre).grid(row=1, column=2)
     
    BoutonQuitter = Button(fenetre, text="Quitter", command=quitter).grid(row=3, column=2)
     
    txtMdp= Label(fenetre, text="Mot de passe",).grid(row=2, column=1)
    entreeMdp = Entry(fenetre).grid(row=2, column=2)
     
    connection(entreeLogin, entreeMdp)
     
    afficherMessage(dossier)
    fenetre.mainloop()
    Mais mon terimnal me dit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Traceback (most recent call last):
      File "pymail.py", line 38, in ?
        afficherMessage(dossier)
    NameError: global name 'dossier' is not defined
    Je sais que je ne maitrise pas trés trés bien les paramètres de fonction et mon probleme vient de la alors si quelqu'un pouvait m'aider un peu ca serait bien sympa !
    Merci


    Vous avez trouvé votre bonheur? Alors hop ca aidera tout le monde !

  2. #2
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    Pour commencer, tu saisis mal l'utilisation du mot clé global: il ne veut pas dire "rend cette variable globale", il veut dire "dans le contexte actuel, utilise la valeur globale de la variable."

    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
     
    x = 10
     
    def foo():
        x = 20
     
    def bar():
        global x
        x = 20
     
    print x
    foo()
    print x
    bar()
    print x

  3. #3
    Membre actif
    Avatar de yorukaze
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    285
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 285
    Points : 299
    Points
    299
    Par défaut
    donc en gros j'ai pas besoin de definir mes variables comme globales vu qu'elles ne sont pas definies dans une fonction c'est ca?


    En effet, ca marche deja mieux :p
    Par contre j'ai desormais un petit soucis, il reconnait pas mes entrées

    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
    import libgmail
    from Tkinter import *
     
     
     
    def afficherMessage():
    	can= Canvas(width=500, height=500, bg='white').grid(row=3, column=1)
     
     
    def connection():
    	connect = libgmail.GmailAccount(login, mdp)
    	connect.login()
    	dossier = connect.getMessagesByFolder('inbox')
    	return dossier
     
    def quitter():
    	fenetre.quit()
     
    #programme principal
     
    fenetre = Tk()
    fenetre.title('Client Gmail')
     
    txtLogin = Label(fenetre, text="Login : ").grid(row=1, column=1)
    txtGmail = Label(fenetre, text="@gmail.com").grid(row=1, column=3)
    login = Entry(fenetre, width=50).grid(row=1, column=2)
    login = str(login)+str("@gmail.com")
     
    txtMdp = Label(fenetre, text="Mot de passe : ").grid(row=2,column=1)
    mdp = Entry(fenetre, width=20).grid(row=2, column=2)
    mdp = str(mdp)
     
    BoutonQuitter = Button(fenetre, text="Quitter", command=quitter).grid(row=3, column=2)
    BoutonConnecter = Button(fenetre, text="connecter", command = connection).grid(row=2, column=3)
     
     
    afficherMessage()
     
    fenetre.mainloop()
    en retour j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Exception in Tkinter callback
    Traceback (most recent call last):
      File "/usr/lib/python2.4/lib-tk/Tkinter.py", line 1348, in __call__
        return self.func(*args)
      File "pymail.py", line 12, in connection
        connect.login()
      File "/usr/lib/python2.4/site-packages/libgmail.py", line 359, in login
        raise GmailLoginFailure("Login failed. (Wrong username/password?)")
    GmailLoginFailure: 'Login failed. (Wrong username/password?)'
    Je pense que mes strings ne doivent pas etre corrects ou alors la fonction de les utilises pas


    Vous avez trouvé votre bonheur? Alors hop ca aidera tout le monde !

  4. #4
    Membre actif
    Avatar de yorukaze
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    285
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 285
    Points : 299
    Points
    299
    Par défaut
    J'ai compris mon erreur:
    en fait, je cherche a exploiter la valeur de Entry en meme temps que son positionnement. J'ai vu dans la faq mon erreur et j'ai corrigé en fonction:

    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
     
     
    txtLogin = Label(fenetre, text="Login : ",bg='#7096b1').place(x=0, y=10)
    txtGmail = Label(fenetre, text="@gmail.com",bg='#7096b1').place(x=160, y=10)
    login = Entry(fenetre, width=15)
    login.pack()
     
     
    txtMdp = Label(fenetre, text="Mot de passe : ",bg='#7096b1').place(x=0,y=35)
    mdp = Entry(fenetre, width=20)
    mdp.pack()
     
    login = str(eval(login.get()))
    mdp = str(eval(login.get()))
    BoutonQuitter = Button(fenetre, text=a, command=quitter).place(x=550, y=500)
    BoutonConnecter = Button(fenetre, text="connecter", command = connection).place(x=550, y=30)
    seulement maintenant, j'ai une autre erreur dont je ne trouve pas la solution sur les forums si faq ni google.
    Voici l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Traceback (most recent call last):
      File "pymail.py", line 38, in ?
        login = str(eval(login.get()))
      File "<string>", line 0
     
        ^
    SyntaxError: unexpected EOF while parsing
    Une idée?


    Vous avez trouvé votre bonheur? Alors hop ca aidera tout le monde !

  5. #5
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Points : 199
    Points
    199
    Par défaut
    Salut,

    Citation Envoyé par yorukaze
    je cherche a exploiter la valeur de Entry en meme temps que son positionnement
    C'est aussi valable pour les widgets Label.
    Dans la syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    variable = Classe().methode()
    Tu récupères le retour de methode, et non l'instance retournée par le constructeur de Classe.


    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    login = str(eval(login.get()))
    mdp = str(eval(login.get()))
    Ouille, pourquoi vouloir faire si compliqué ?
    Entry.get() retourne déjà une chaîne, donc inutile de la convertir encore en chaîne avec le constructeur str. Et que vient faire la fonction eval ?
    En plus tu récupères deux fois login.get(), au lieu de récupérer ensuite le mot de passe.
    Et pourquoi écraser les références des widgets ?
    Cela suffit :

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    str_login = login.get()
    str_mdp = mdp.get()

    Passons maintenant au placement : place est un très mauvais choix.
    Dans ton cas, les widgets se chevauchent et on ne voit rien du tout.
    place trouve son utilité lorsque tu veux faire un placement absolu, c'est à dire quasiment jamais.
    Je conseille pack, qui est le plus simple et très configurable.
    grid peut être une alternative intéressante dans le cas de conception de formulaires, ce qui est ton cas.
    Je rappelle au passage que l'on ne peut pas mélanger différents gestionnaires de placement : pack, grid et place s'excluent mutuellement.


    Il y a aussi une mauvaise compréhension du comportement de l'interface graphique : tu traites tes saisies comme si tu étais en console, en programmation séquentielle.
    Le fait d'afficher un widget Entry ne va pas mettre ton programme en pause !
    Ici, tu demandes à Python : construis un widget Entry et positionne-le.
    Mais toi, l'utilisateur, tu seras libre de saisir ton texte n'importe quand.

    C'est le concept de la programmation événementielle : ton programme va réagir aux évènements. On « attache » un évènement à une fonction, et la fonction est appelée quand l'évènement se produit : c'est ce que tu fais avec les boutons.
    On va donc récupérer les saisies dans la fonction connexion.
    Voici le code corrigé et brièvement commenté :
    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
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
     
    import libgmail
    from Tkinter import *
     
     
    def connexion():
    	# on récupère les saisies
    	str_login = login.get() + "@gmail.com"
    	str_mdp = mdp.get()
     
    	connect = libgmail.GmailAccount(str_login, str_mdp)
    	connect.login()
    	dossier = connect.getMessagesByFolder("inbox")
     
     
    fenetre = Tk()
    fenetre.title("Client Gmail")
     
    # pour les Labels, inutile de stocker les références, on en a pas besoin
    Label(fenetre, text="Login : ", bg='#7096b1').grid(row=0, column=0)
    # par contre, on doit conserver les références des Entrys
    login = Entry(fenetre, bg="white")
    login.grid(row=0, column=1)
     
    Label(fenetre, text="Mot de passe : ",bg='#7096b1').grid(row=1, column=0)
    mdp = Entry(fenetre, bg="white")
    mdp.grid(row=1, column=1)
     
    # inutile de conserver les références des boutons
    Button(fenetre, text="Quitter", command=fenetre.destroy).grid(row=2, column=0)
    Button(fenetre, text="Connecter", command=connexion).grid(row=2, column=1)
     
    fenetre.mainloop() # boucle principale qui intercèpte les évènements
    Bon, il reste encore beaucoup de choses à faire :
    • Gérer le cas où la connexion n'aboutit pas (mauvais mot de passe, etc)
    • Améliorer l'interface
    • J'ai aussi enlever le return de la fonction, car cette valeur n'était récupérée nul part... à toi de voir comment il faut traiter les données de dossier


    Je te conseille aussi de lire des tutoriels et la documentation de Tkinter

    Quelles seront les fonctionnalités de ton client mail ? Tu dois d'abord penser à comment sera l'interface et les fonctionnalités qu'elle proposera.

    Par exemple, le widget Text me semble tout à fait approprié pour lire et écrire un mail.
    Le widget Listbox pourrait lister les mails et en cliquant sur l'un des éléments du Listbox, cela chargerait le contenu du mail dans un widget Text.

    La connexion (saisie du login et du mot de passe) pourrait se faire via une fenêtre pop-up, la fenêtre principale resterait dédiée à la lecture et à l'écriture des emails.

    Enfin bref, ce ne sont que des idées, à toi de voir ce que tu veux réaliser. Mais tu dois d'abord penser aux composants qui seront utilisés par ton application, et comment ils vont interagir entre eux.
    <3 Debian
    [ C | C++ | PHP | Python ]

  6. #6
    Membre actif
    Avatar de yorukaze
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    285
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 285
    Points : 299
    Points
    299
    Par défaut
    oulala je ne sais pas quoi dire !
    Je vais tout simplement te dire merci Haze, tes explications me sont trés utiles.
    En ce qui concerne le programme, tu dois bien t'apercevoir que je débute avec pythn. J'ai sous la main le livre de Gérard Swinnen qui m'aide beaucoup. Seulement voila, le livre en questions n'utilises pas toute les méthodes de placement de python , il est donc dufficile de choisir le bon en fonction des projets.

    # inutile de conserver les références des boutons
    Button(fenetre, text="Quitter", command=fenetre.destroy).grid(row=2, column=0)
    Button(fenetre, text="Connecter", command=connexion).grid(row=2, column=1)
    je ne vois pas trop ce que signifie ce commentaire. Tu parlais de la référence a la fonction quitter pour le bouton quitter? Oui je te l'accorde je l'avais fait pour travailler avec les fonctions c'est donc purement didactique .


    Pour l'evolution du programme, voici la suite:
    - Mise en place de la récupération des mails dans l'appli+ tri pour afficher tous les message ou les x dernier ou les non lus ou les nouveaux...
    - Passer l'appli sous forme de classe pour structurer un peu (la on va rigoler)
    - rajouter des fonctions:
    • Fonctions pour lire et ecrire des messages
    • fonction pour supprimer des messages
    • Passer l'appli en notification pour la faire tourner en background et prévenir si un mail arrive


    Voila la finalité de mon appli. Il reste encore énormement de chemin mais la rapidité de compréhension de python me facilite beaucoup la tache !


    Vous avez trouvé votre bonheur? Alors hop ca aidera tout le monde !

  7. #7
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Points : 199
    Points
    199
    Par défaut
    De rien

    Citation Envoyé par yorukaze
    le livre en questions n'utilises pas toute les méthodes de placement de python , il est donc dufficile de choisir le bon en fonction des projets.
    De mémoire, le livre explique grid et pack. Comme je l'ai dit, place est vraiment spécial...
    L'avantage de pack est que l'on peut faire du placement relatif (si tu connais la mise en forme de pages web avec CSS, ça ressemble un peu aux float: left; par exemple).
    grid se comporte comme un tableau avec ses lignes et ses colonnes.
    Ça devient vite lourd d'indiquer les numéros de ligne et de colonne à chaque placement, cependant dans les formulaires, on cherche souvent à avoir les textes et les champs de saisies bien alignés, donc je conseille grid pour ce cas.

    Citation Envoyé par yorukaze Voir le message
    je ne vois pas trop ce que signifie ce commentaire. Tu parlais de la référence a la fonction quitter pour le bouton quitter? Oui je te l'accorde je l'avais fait pour travailler avec les fonctions c'est donc purement didactique .
    Non je ne parlais pas de ça : dans ton code, tu mémorises dans des variables les instances de chaque widget créé (désolé, le terme référence était ambigu, en Python toute les variables sont des références vers des objets...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    BoutonQuitter = Button(fenetre, text=a, command=quitter).place(x=550, y=500)
    BoutonConnecter = Button(fenetre, text="connecter", command = connection).place(x=550, y=30)
    (En l'occurence, c'est None que tu mémorises dans BoutonQuitter et BoutonConnecter, voir mon premier post sur variable = Classe().methode() ).

    Je dis juste qu'il est inutile de mémoriser les instances des widgets quand on en a pas besoin, en gros on a deux formes de création de widgets en Tkinter :
    - Quand tu auras besoin de l'instance plus tard, comme c'est le cas avec Entry car on devra récupérer la saisie de l'utilisateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    variable = Widget(parent)
    variable.pack()
    - Dans le cas de widgets simples, comme les Labels et Buttons, on a rarement besoin de mémoriser l'instance, on peut donc les créer en une seule ligne :
    (En réalité, l'instance est stockée en interne par Tkinter, elle n'est pas perdue. Tu peux la retrouver dans l'attribut children du widget parent, qui est un dictionnaire contenant les instances de tous ses widgets enfants)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> from Tkinter import *
    >>> root = Tk()
    >>> Button(root, text="click").pack()
    >>> print root.children
    {'-1210345428': <Tkinter.Button instance at 0xb7db982c>}
    Bon, on ne s'en sert quasiment jamais, mais c'était juste pour démontrer que les instances des widgets sont toujours mémorisées quelque part.

    J'ai aussi débuté en Tkinter avec le livre de G. Swinnen, il est très pédagogique mais ne remplace en aucun cas une bonne documentation :
    http://effbot.org/tkinterbook/
    http://infohost.nmt.edu/tcc/help/pubs/tkinter/

    Vu tes messages d'erreurs, tu sembles être sous une machine GNU/Linux, si c'est le cas tu as plein d'exemples dans le répertoire /usr/share/doc/python-tk

    En tout cas c'est bien de se donner un projet à réaliser, ça fait beaucoup progresser.
    Moi j'avais choisi de faire un jeu du serpent (et effectivement j'ai appris beaucoup avec)

    Bonne continuation.

    Note aux modérateurs : topic à déplacer dans le forum Tkinter ?
    <3 Debian
    [ C | C++ | PHP | Python ]

  8. #8
    Membre actif
    Avatar de yorukaze
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    285
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 285
    Points : 299
    Points
    299
    Par défaut
    Merci pour ces derniers éléments.
    Je vois maintenant la différence entre les pack(), grid() et place().
    Pour ce qui est de mon système en effet je suis sous Debian quelques années parce que ca rox un max !
    Je suis allé voir ton site et donc ton serpent en C qui n'a pas l'aire mal comme ton site et les différents projet. Je suis aussi en phase de dev pour un site (pour l'instant php.mysql mais peut etre bientot django)

    Merci a toi.

    Info modo: je suis ok avec Haze pour deplacer en Tkinter


    Vous avez trouvé votre bonheur? Alors hop ca aidera tout le monde !

  9. #9
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Points : 199
    Points
    199
    Par défaut
    Citation Envoyé par yorukaze
    Pour ce qui est de mon système en effet je suis sous Debian quelques années parce que ca rox un max !
    Évidemment que Debian rox

    Citation Envoyé par yorukaze
    ton serpent en C
    Ben non. C'est que du Python/Tkinter, je ne t'en aurais pas parlé sinon.
    Peut être trouveras-tu quelque chose d'intéressant dans les sources.
    <3 Debian
    [ C | C++ | PHP | Python ]

  10. #10
    Membre actif
    Avatar de yorukaze
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    285
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 285
    Points : 299
    Points
    299
    Par défaut
    Citation Envoyé par Haze. Voir le message
    Évidemment que Debian rox


    Ben non. C'est que du Python/Tkinter, je ne t'en aurais pas parlé sinon.
    Peut être trouveras-tu quelque chose d'intéressant dans les sources.
    Oops j'ai lu beaucoup trop vite
    Le C quand tu l'as apprivoiser c'est un régal


    Vous avez trouvé votre bonheur? Alors hop ca aidera tout le monde !

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

Discussions similaires

  1. [PHP 5.2] Probleme avec les fonctions fopen fwrite
    Par zeyro dans le forum Langage
    Réponses: 2
    Dernier message: 20/02/2009, 15h34
  2. probleme avec les fonction get et set
    Par Invité dans le forum Flex
    Réponses: 0
    Dernier message: 23/01/2008, 14h44
  3. [Visual C++]probleme avec les fonctions declarées static
    Par sana06 dans le forum Visual C++
    Réponses: 2
    Dernier message: 20/07/2007, 11h21
  4. problemes avec les fonction de string en c++
    Par magniaco dans le forum C++
    Réponses: 13
    Dernier message: 08/10/2006, 15h28
  5. problème avec les fonctions MidStr et LeftStr
    Par timsah dans le forum C++Builder
    Réponses: 1
    Dernier message: 07/02/2006, 10h07

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