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

Python Discussion :

Fonction pour créer des variables


Sujet :

Python

  1. #1
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut Fonction pour créer des variables
    Bonjour.
    J'ai fait les fonctions suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def var(variable,value):
        globals()[variable]=value
        return variable+'='+str(value)
    def rmvar(variable):
        globals()[eval(variable)]=None
        return ""
    Ça ne marche pas. Quelqu'un sait pourquoi ?
    Je galère la dessus depuis tout à l'heure, et je trouve pas.
    Merci.

  2. #2
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Citation Envoyé par Spitfire 95 Voir le message
    Ça ne marche pas. Quelqu'un sait pourquoi ?
    Je galère la dessus depuis tout à l'heure, et je trouve pas.
    Merci.
    C'est le rmvar qui ne fonctionne pas ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> def newvar(variable, value):
    ...     globals()[variable]=value
    ... 
    >>> def rmvar(variable):
    ...     del globals()[variable]
    ... 
    >>> newvar('A', 10)
    >>> print globals()
    {'A': 10, '__builtins__': <module '__builtin__' (built-in)>, 'rmvar': <function rmvar at 0xb77565dc>, 'newvar': <function newvar at 0x93463e4>, '__name__': '__main__', '__package__': None, '__doc__': None}
    >>> rmvar('A')
    >>> print globals()
    {'__builtins__': <module '__builtin__' (built-in)>, 'rmvar': <function rmvar at 0xb77565dc>, 'newvar': <function newvar at 0x93463e4>, '__name__': '__main__', '__package__': None, '__doc__': None}
    Ce n'est ('presque') qu'un dico après tout.
    Sinon j'ai fais une class (sur le modèle de la class variable de Tkinter get/set/callback..., dont je te recommande la lecture du code) dans ce sens si cela t'intéresse.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    Merci. En fait, RIEN ne marche. Ça fait deux mois que j'ai fait la fonction var, et il me semblait pourtant avoir testé, et ça marchait. Là, je modifie la fonction pour enregistrer les variables dans un fichier de configuration via configparser, rien ne marche plus. J'ai résolu pour cfgparser, mais ça ne marche toujours pas.
    Si vous voulez voir le code complet, l'archive installable est là : http://free-apps.evoconcept.net/down...latrice.tar.gz
    Attention, l'installation n'est possible que sous un système GNU/Linux.
    Le plus étrange, c'est qu'au début de mon code, j'ai ça qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for variable in cfg.options("Vars"):
         globals()[variable]=cfg.getfloat('Vars',variable)
    Je ne comprend pas d'où vient le problème. Un conflit entre la variable variable, locale à la classe et la variable global()[variable] ? Mais je ne vois pas comment contourner le problème. J'ai pensé aux alias de variables, mais ça ne m'avance pas beaucoup puisque si j'en change une, l'autre sera changée elle aussi.

    Merci.

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Moi, je trouve que ça marche! Voilà ce que j'ai fait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    def var(variable,value):
        globals()[variable]=value
     
    var('A', 'toto')
     
    print A
    toto
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    def rmvar(variable):
        del globals()[variable]
     
    rmvar('A')
     
    print A
     
    Traceback (most recent call last):
      File "D:\Python\Pydev\test\test_AAR.py", line 25, in <module>
        print A
    NameError: name 'A' is not defined
    Et l'affichage du dictionnaire globals() reflète bien les opérations réalisées.

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    Non, ça marche pas chez moi. Je suis sous Ubuntu 10.10 avec Python 2.6.6.
    Voici le code complet des deux fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def var(variable,value):
        """Crée une variable globale"""
        cfg.set("Vars",variable,value)
        cfg.write(open('.calculatrice/preferences.cfg','w'))
        globals()[variable]=value
        return variable+'='+str(value)
    def rmvar(variable):
        """Supprime une variable créée"""
        cfg.remove_option("Vars",variable)
        cfg.write(open('.calculatrice/preferences.cfg','w'))
        del globals()[variable]
        return ""
    Aucune erreur retournée, mais si je demande la variable, j'ai toujours une erreur "name [variable] is not defined".

    Et j'ai un autre problème, les variables enregistrées, comment choisir le bon type de données ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for variable in cfg.options("Vars"):
        globals()[variable]=cfg.getfloat('Vars',variable)
    J'avais pas pensé aux str. Comment choisir entre str et nombre ? Et entre int et float ? Moins important, mais ce serait plus pratique et plus économique pour la mémoire.
    Merci.

    Et @tyrtamos : Avec toute l'aide que vous m'avez apporté et les fonctions que je vous ai volées empruntées, je devais vous mettre dans les crédits. Je vous met comment dans ce code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Label(c,text=_("Autres contributeurs"),font=bold).grid()
            Label(c,text=_("Arthur C.  Testeur des premières versions\nLes membres de python.developpez.com\nLes membres d'Ubuntu-fr.org\n")).grid()
    Et aux autre qui m'ont aidé, j'ai aussi pensé à vous, de façon groupée

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Je viens d'essayer le code que j'ai proposé plus haut sur ubuntu 10.10 (Python v2.6.6) et: ça marche pareil!

    Reprend mes fonctions et ajoute progressivement tes compléments pour savoir ce qui coince.

    Sinon, je suis ravi de t'avoir inspiré des morceaux de codes: ils sont là pour ça. Il te suffit de citer tes sources comme je le fais moi-même.

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  7. #7
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    En terminal, pas de problème. Mais avec mon programme, ça ne fonctionne pas.
    Résumé de l'architecture du programme :

    def var(variable,value)
    def rmvar(variable)
    class Calculatrice
    def calc

    Peut-être que le problème vient de l'utilisation des classes. Si je mettais var et rmvar dans Calculatrice().calc(), je pourrais réutiliser les variables dans le programme. Mais il faudrait qu'elles restent globales pour être réutilisées par les plugins.
    J'adore les bugs inexplicables comme ça Surtout quand ça marche puis que deux mois après ça marche plus. Comme pour les thread qui se stoppaient, puis qui devenaient incontrôlable deux mois après ^^ Vive les processus. Et encore merci pour la résolution de mon problème de thread et de processus, tyrtamos

  8. #8
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir,

    Citation Envoyé par Spitfire 95 Voir le message
    Peut-être que le problème vient de l'utilisation des classes. Si je mettais var et rmvar dans Calculatrice().calc(), je pourrais réutiliser les variables dans le programme. Mais il faudrait qu'elles restent globales pour être réutilisées par les plugins.
    Tu viens de donner la réponse : C'est un problème de porté de variable. Si tu utilise des class tu n'as qu'a faire un print de globals() dans l'__init__ et tu verras Il n'y à pas qu'un seul globals().

    Voici ce que je fais pour le type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        def __init__(self, master=None, value=None, trace=None, mode=None):
            if value is not None:
                self._value=value
            else:
                self._value=self._default
            self._type=type(self._value)
    ...
        def type(self):
            # Return type
            return self._type
    @+
    Merci d'utiliser le forum pour les questions techniques.

  9. #9
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    Merci, maintenant, je sais d'où vient le problème. Mais... je fais comment ? Je mets mes fonctions dans la classe ? Mais après, comment rendre mes globals globales ? Si on ne peut pas appeler les fonctions depuis les plugins, ce n'est pas grave, du moment que j'ai les variables en commun. Puis l'interface n'étant pas créée dans un __init__, les fonctions devraient pouvoir être appelées de l’extérieur.
    Bref, je met quoi où ?
    Merci.

  10. #10
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir,

    Pourquoi ne pas utiliser ton propre dico ou une class de stockage plutôt que globals() ? Tu est sur de ne pas avoir de problème de portée et un message d'erreur si c'est le cas.
    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> class myvars():
    ...     unevar=None
    ... 
    >>> myvars.unevar=1
    >>> type(myvars.unevar)
    <type 'int'>
    Ou si tu préfère tu peux mettre un dico dans ta class.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  11. #11
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    Parce que ça ne répond pas à mon besoin, ou alors je ne comprend pas comment l'utiliser pour l'adapter à ce besoin.
    Je ne veux pas créer de variable, je veux permettre à l'utilisateur de ma calculatrice de créer ses propres variables. Donc je ne peux pas savoir à l'avance quel nom il lui donnera ou le type (le type étant important pour le chargement des variables enregistrées dans le fichier de configuration).
    Et il ne faut pas demander à un utilisateur de faire des manipulations compliquées, même si la création de variables n'est pas pour l'utilisateur lambda, elle doit rester simple d'accès.
    Merci.

  12. #12
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Ou si tu préfère tu peux mettre un dico dans ta class.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> class myvars():
    ...    vars={}
    ... 
    >>> myvars.vars['lenomdelavar']=1
    >>> myvars.vars['lenomdelavar2']='test'
    >>> print myvars.vars
    {'lenomdelavar': 1, 'lenomdelavar2': 'test'}
    >>> print type(myvars.vars['lenomdelavar'])
    <type 'int'>
    >>> print type(myvars.vars['lenomdelavar2'])
    <type 'str'>
    >>> etc... ;)
    C'est un dico dans une class, dico de même que globals(), mais unique.
    De ce fait s'il n'est pas disponible dans le namespace cela te retourne une erreur.

    Bon code.
    Merci d'utiliser le forum pour les questions techniques.

  13. #13
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut

    Ça devient compliqué là. Imaginez le pauvre utilisateur qui devra taper "MyVars.vars['variable']" pour avoir le résultat. Non, bien trop complexe... Ne serait-il pas possible que les globals() le soient réellement ? Que ma classe considère le dico globals comme un vrai variable globale ?
    Merci.

  14. #14
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Salut,
    Citation Envoyé par Spitfire 95 Voir le message
    Imaginez le pauvre utilisateur qui devra taper "MyVars.vars['variable']" pour avoir le résultat. Non, bien trop complexe...
    Il n'y a pas d'interpréteur dans ta calculatrice? C'est ça le problème. L'utilisateur devrait pouvoir taper variable et ton programme devrait l'interpréter comme MyVars.vars['variable']

    A+

    Pfeuh

  15. #15
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    En fait, dans une calculatrice, quand on veut permettre à un utilisateur de créer/utiliser ses propres variables, on se heurte à 2 problèmes:

    - l'affectation 'A = expression' est une instruction et non une expression. Elle ne peut donc être résolue avec eval. Si on veut se passer d'exec, il faut faire une préanalyse (recherche de '=' précédé par un nom de variable syntaxiquement correct) avant de lancer eval sur la suite.

    - en acceptant la création de variables utilisateur mélangées avec celles du programme, on risque des 'collisions' (du genre: sin = 2*5 et calculs ultérieurs avec sin()).

    Je crois alors qu'il faut gérer les variables 'utilisateur' dans un simple dictionnaire, et passer ce dictionnaire comme 2ème argument d'eval, comme sa syntaxe le permet. C'est ce que j'utilise actuellement, mais les masquages de variables globales restent possibles, puisque globals() reste nécessaire au calcul.

    Peut-être faudrait-il ajouter un caractère distinctif à ces variables utilisateurs comme ça existe dans certains langages: 'A$' au lieu de 'A', en plus de les gérer dans un dictionnaire spécifique ??

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  16. #16
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    Je me suis déjà posé la question du conflit des variables. Et à ma grande surprise, en créant une variable avec globals() du même nom qu'une variable globale du programme qui contenait l'historique des calculs, l'historique restait, et quand l'utilisateur demandait sa variable, s'était bien la variable qu'il avait créée qui était retournée.
    Et j'ai compris pourquoi mon code marchait mais ne marche plus : j'ai créé la fonction var avant de terminer de réécrire le programme avec des classes, et les fonctions de la class Calculatrice étaient des fonctions racine du programme.
    Donc si il y a quand même un risque de conflits, je vais voir pour créer un dico, et des variables raccourcis (var=Variables.var, par exemple, après m'être assuré que Tkinter n'ai pas de classe Variables avec un s), et d'autres trucs comme ça pour rendre l'utilisation plus simple, même si le code et la mémoire utilisée vont en subir les conséquences.
    Merci.

  17. #17
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    J'ai quand même envie de revenir sur les globals qui pourraient me simplifier la tâche et le code. En fait, il y a un détail que je ne comprend pas et qui pourrait être la clé de mon problème.
    À la racine de mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cfg=RawConfigParser()
    cfg.read('.calculatrice/preferences.cfg')
    for variable in cfg.options("Vars"):
        globals()[variable]=cfg.getfloat('Vars',variable)
    Les variables ainsi crées fonctionnent ensuite dans le programme, malgré les classes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def var(variable,value):
        globals()[variable]=value
        return variable+'='+str(value)
    Les variables créées par cette fonction ne fonctionnent pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    def vars():return cfg.options("Vars")
    Lors de l'appel de cette fonction, toutes les variables chargées par le premier code (celui à la racine) s'affichent dans un tuple. Pourtant, l'espace de noms devrait être le même. Ou alors je dois déclarer les variables crées avec globals() comme globales en haut de la fonction, mais comme cela fonctionnait avant qu'il y ait les classes, l'espace de noms est forcement le même.
    Puis en se qui concerne les conflits, je peux appeler la variable avec un try, si pas d'erreur on teste que la variable n'ai pas été créée manuellement (pas dans le fichier de config), et donc si la variable n'existe pas (exception) ou si elle est déjà définie mais bien par l'utilisateur, on peux la créer ou la changer. Et je ne risque à priori pas de conflit avec var('sin',sin(x)) puisque sin retournera <built-in function sin>, donc pas d'erreur.

  18. #18
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    Après avoir testé si l'instruction à la racine du code lancée dans cette fonction depuis la classe fonctionnerai, je remarque que non. Sinon, j'aurais pu recharger les variables enregistrées depuis le fichier. Mais avec des fichiers longs cela risquerai de prendre un peu de temps. Quoi que...

    Puis j'ai ensuite essayé de passer par sys.modules. Donc si je lance modules['__main__'].var('toto',5) dans mon champ de calcul, donc de ma classe, je penserais que la fonction agirait comme si je l'appelais depuis le niveau racine, mais non.

    Je suis à court d'idées. Personne n'a de solution simple et user-friendly ?
    Merci.

  19. #19
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    J'ai tenté d'utiliser un dico. Voici la partie du code qui est intéressante :
    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
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
    def var(variable,value):
        """Crée une variable globale"""
        if not variable in globals():
            cfg.set("Vars",variable,value)
            cfg.write(open('.calculatrice/preferences.cfg','w'))
            variables[variable]=value
            return variable+'='+str(value)
        else:raise ValueError(_("Ce nom de variable n'est pas disponible"))
    def rmvar(*var):
        """Supprime une variable créée"""
        for variable in var:
            cfg.remove_option("Vars",variable)
            cfg.write(open('.calculatrice/preferences.cfg','w'))
            del variables[variable]
        return ""
    def vars():
        """Retourne les variables globales enregistrées"""
        return variables
    class Calculatrice:
        def calc(self):
            """Affichage de la calculatrice"""
            global entree,unite,f1
     
            try:f1.destroy()
            except:pass
     
            f1=Frame(f)
     
            self.f2=Frame(f1)
     
            entree=Entry(self.f2,width=25,justify='right')
            entree.bind("<<Action>>",self.startCalc)
            entree.bind('<Escape>',self.stopCalc)
            entree.grid(row=0,column=1)
     
            self.f2.grid()
     
            f1.grid()
     
        def startCalc(self,event=""):
            """Lance le calcul dans un processus"""
     
            def evaluate(expression,resultat):
                global variables
                """Calcule dans un processus l'expression et renvoie le résultat
                resultat[0] renvoie False si erreur de calcul
                resultat[1] renvoie le resultat ou l'erreur selon resultat[0]"""
                c,G,R,Na,k=299792458,6.67300e-11,8.314472,6.02214e23,9e8    # Définition des constantes
                try:
                    resultat[1]=str(eval(expression,globals(),variables))
                    resultat[0]=True
                except:
                    resultat[1]=str(sys.exc_info()[1])
                    resultat[0]=False
     
            if entree.get().strip():    # On ne lance le calcul que si l'entrée n'est pas vide
                self.arretdemande = False
                self.resultat = Manager().dict()
                self.resultat[0] = None
                self.expr=entree.get()
                self.calcul = Process(target=evaluate,args=(self.expr,self.resultat))
                self.calcul.start()
     
                histCalculs.append(entree.get())        # Ajout à l'historique des expressions entrées
                entree.configure(state='disabled')      # On désactive le champ de texte pour que l'utilisateur ne puisse pas lancer un calcul pendant un autre calcul
                # On réinitialise le champ d'erreur et l'infobulle
                self.label_erreur.configure(text='')
                self.ib_erreur.label.configure(text='')
                self.ib_erreur.texte=''
                self.boutonCalcul.configure(text='Stop',command=self.stopCalc)
     
                f1.after_idle(self.affiche)
        def affiche(self):
            global varHist,histCalculs,nCalcul,sauvegarder_hst
     
            if not self.calcul.is_alive():  # affiche le résultat s'il est disponible
     
                entree.configure(state='normal')
                if self.arretdemande:
                    self.resultat[0]=False
                    self.resultat[1]=_("Arrêt du calcul demandé")
     
                if self.resultat[0]:    # pas d'erreur de calcul => afficher le résultat
                    entree.delete(0,'end')
                    entree.insert(0,self.resultat[1])
                else:   # afficher l'erreur de calcul
                    self.label_erreur.configure(text=_("Erreur: ")+self.resultat[1],bg='#FF5050')
                    self.label_erreur.after(1000,lambda:self.label_erreur.configure(bg='#D9D9D9'))
                    if len(self.resultat[1])>44:
                        self.ib_erreur.label.configure(text=self.resultat[1])
                        self.ib_erreur.texte=self.resultat[1]
     
                varHist+=self.expr+' = '+self.resultat[1]+'\n'  # Ajout à l'historique
                nCalcul=len(histCalculs)
                if sauvegarder_hst.get()==1:Historique().update_hst()
     
                self.boutonCalcul.configure(text=_('Calculer'),command=self.startCalc)
     
            else:f1.after_idle(self.affiche)
    variables={}
    # Chargement / Création du fichiers des parametres
    cfg=RawConfigParser()
    try:
        cfg.read('.calculatrice/preferences.cfg')
     
        unite=IntVar(value=cfg.getint('Config','unite'))
        sauvegarder_hst=BooleanVar(value=cfg.getboolean('Config','sauvegarder_hst'))
     
        for variable in cfg.options("Vars"):
            try:variables[variable]=cfg.getfloat('Vars',variable)   # Variables numériques => float
            except:variables[variable]=cfg.get('Vars',variable)     # Variables str
    except:
        cfg.add_section('Config')
     
        cfg.set('Config','sauvegarder_hst','1')
        cfg.set('Config','unite','1')
     
        cfg.add_section('Vars')
     
        cfg.write(open('.calculatrice/preferences.cfg','w'))
     
        unite=IntVar(value=1)
        sauvegarder_hst=BooleanVar(value=1)
    Le code n'est pas fonctionnel puisqu'il est incomplet, mais pour l'utilisation du dico, je pense que c'est plus simple qu'un long discours. Et si certains ont besoin de mon code pour enregistrer ou charger les variables, c'est encore mieux. Donc qu'est-ce qui ne va pas ?
    J'ai l'impression que au chargement les variables créées sont prises en compte, puis que celles créées par la suite ne sont pas prise en compte dans ma classe, comme si il ne mettait pas à jour le contenu de eval(expr,globals(),variables). J'ai essayé de passer variable en argument, de déplacer la fonction au niveau racine (puisqu'elle est indépendante de la classe), de mettre global variables à plusieurs endroits... Rien ne fonctionne. Je n'ai pas encore essayé de mettre variables={} dans Main.__init__(self) mais ce ne serait ni logique ni propre (Main étant une classe basée sur Tix.Tk().

    ==EDIT==
    Même en le mettant dans la classe, ça ne fonctionne pas. Même problème.

  20. #20
    Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2010
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2010
    Messages : 83
    Points : 46
    Points
    46
    Par défaut
    J'ai enfin résolu mon problème !!!
    Après de nombreux essais, quelques tasses de thé (j'aime pas le café ), quelques touffes de cheveux arrachées, et un gros trou dans le mur qui a eu le malheur de se mettre à portée de mon point pendant que je codais, j'ai réussi ! (ok, j'exagère, j'ai pas bu beaucoup de thé xD)
    Le véritable problème n'était pas la classe, mais le fait que le calcul soit appelé dans un processus depuis une méthode de ma classe. Et donc le dico passait... très bizarrement. Après quelques testes, j'ai compris que je comprenait rien à la logique de Python
    Et j'ai vu dans mon code resultat=Manager().dict() (merci à Tyrtamos pour les processus). Et là, j'ai réalisé l'origine du problème. Donc en remplaçant variable={} par variables=Manager().dict(), tout fonctionne.
    Voila, donc si maintenant quelqu'un est confronté au même problème, il a la (ou une, je sais pas) solution.
    Merci encore.

Discussions similaires

  1. [IP-2010] Créer des "variables" temporaire pour l'affichage des titres
    Par MrMeteo dans le forum InfoPath
    Réponses: 1
    Dernier message: 26/02/2014, 20h56
  2. Comment créer des variables pour chaque ligne d'une table
    Par Slyvore dans le forum Développement de jobs
    Réponses: 4
    Dernier message: 24/04/2012, 14h24
  3. Réponses: 35
    Dernier message: 14/11/2008, 15h30
  4. Créer une fonction pour remplacer des caractères
    Par virtuadrack dans le forum C++
    Réponses: 4
    Dernier message: 11/09/2008, 14h52
  5. Créer fonctions pour saisir des nombres
    Par odsen.s dans le forum C
    Réponses: 34
    Dernier message: 30/04/2007, 19h34

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