Comment executer des fonctions à partir de paramètres, le tout défini dans un fichiers

Le problème exposé dans ce sujet a été résolu.

Bonjour :)

Ce titre est… le mieux que j’ai put faire et n’explique sûrement pas grand chose. Je vais donc vous expliquer le but que j’aimerais atteindre et vous expliquer ensuite comment je souhaiterais le faire (pratiquement je ne sais pas, théoriquement oui). Du coup j’aimerais savoir comment on fait dans la pratique et surtout si c’est une bonne idée (si ça ne l’est pas, comment faire autrement).

Je suis en train de développer un logiciel de traitement d’images (aucune importance) qui a une interface. Il m’est demandé de séparer l’interface et la partie traitement d’images (et de données) de l’interface. Le tout étant en python, je ne peux pas "remonter" l’architecture de mon projet, qui est comme suit :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
├── data
│   ├── plotting.py
│   ├── processing.py
│   ├── saving.py
│   └── utils.py
├── gui
│   ├── controller
│   ├── model
│   │   ├── gallery.py
│   │   ├── image.py
│   │   └── plot.py
│   └── view
├── image
│   ├── analysis.py
│   ├── preprocessing.py
│   ├── processing.py
│   └── utils.py
├── main.py
├── hyph.py
├── junction.py
├── saving.py
└── tree.py

Mon problème est donc, je ne peux pas appeler mes fonctions développés dans les dossiers "image" et "data" depuis mes contrôleurs, ni les scripts (hyph, junction, saving et tree) (qui sont en fait une compilation des fonctions de "image" et "data"). J’aimerais donc avoir un moyen d’executer les fonctions que je souhaite (notamment dans les scripts), c’est à dire quand je clique sur un bouton.

Pour ce faire, je me suis souvenu de ma minuscule expérience de Symfony2 et je me suis rappelé le "routage" et m’en suis inspiré à partir de souvenirs. Dans mon main, je lance mon interface et attend l’action souhaitée. J’appelle donc une fonction ("run" en l’occurence) qui me renvoie l’action ("skeleton" par exemple) et les données dont j’ai besoin, j’execute ensuite le script approprié puis appel la fonction "send" qui me permet de donner le resultat. Voici l’implémentation du main :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def main():
    end = False

    while not end:
        todo, data = manager.run()

        if todo == "end":
            end = True
        elif todo == "skeleton":
            tosend = hyph.skeleton(data)
        elif todo == "heads":
            tosend = junction.get_heads(data)
        elif todo == "junctions":
            tosend = junction.get_junctions(data)

        if todo != "end":
            manager.send(todo, tosend)

Comme vous le voyez, c’est pas propre du tout, et en plus un peu chiant. Ce que j’aimerais faire, c’est avoir un fichier du type :

1
"skeleton":{function:"hyph.skeleton", data:"Image originelle"}

(J’ai utilisé une syntaxe random, qui ressemble un peu aux dictionnaires)

J’aimerais donc savoir si c’est une bonne idée, ensuite (si ça l’est) si le mieux c’est d’avoir un fichier avec un dictionnaire énorme qu’on alimentera au fur et à mesure ou s’il existe d’autres méthodes (genre avec du json ou autre).

J’espère avoir été clair, n’hésitez pas à me demander plus de précision.

Merci d’avance :)

+0 -0

Salut !

Pourquoi tu ne peux pas appeler les fonctions depuis ton contrôleur ? Si c’est juste les chemins dans ton arborescence, dans ce cas la tu peux. (préfixe le bon nom avec un point, et rajoute des fichiers __init__.py).

+1 -0

Bonjour,

Mon problème est donc, je ne peux pas appeler mes fonctions développés dans les dossiers "image" et "data" depuis mes contrôleurs, ni les scripts (hyph, junction, saving et tree) (qui sont en fait une compilation des fonctions de "image" et "data"). J’aimerais donc avoir un moyen d’executer les fonctions que je souhaite (notamment dans les scripts), c’est à dire quand je clique sur un bouton.

Ricocotam

On est d’accord que ce n’est pas une impossibilité technique, mais que tu ne veux pas le faire pour garder le contrôleur indépendant de ces modules ?

Sinon, pour ta solution, tu peux effectivement avoir un gros dictionnaire association une fonction à chaque nom. Dictionnaire que tu pourrais garder dans un fichier séparé. Une autre idée serait d’alimenter dynamiquement ce dictionnaire, à l’aide d’un décorateur sur tes fonctions.

@Unidan j’avoue que je ne connais pas cette technique, mais je veux bien en savoir plus. Je m’en servirait pas dans le cadre de ce projet mais je veux bien savoir de quoi tu parles :)

@entwanne Visiblement mon cerveau tourne encore rond alors ^^. L’alimenter directement avec les décorateurs ? J’avoue ne pas trop voir l’intérêt (sachant qu’il ne bougera pas au fil de l’execution du programme), de plus le but d’avoir une doc c’est que ceux qui bossent sur l’interface et ceux sur les scripts puissent se mettre d’accord sans avoir besoin de poser pleins de questions. Mais je veux bien savoir quel serait l’intérêt en plus d’un truc statique :)

@Unidan j’avoue que je ne connais pas cette technique, mais je veux bien en savoir plus. Je m’en servirait pas dans le cadre de ce projet mais je veux bien savoir de quoi tu parles :)

Avec une structure comme la suivante :

1
2
3
4
5
6
7
.
└── project
    ├── core
    │   └── foo.py
    ├── gui
    │   └── bar.py
    └── __main__.py

Où tu lancerais ton programme par un python -m project, tu peux accéder aux fonctions/classes de core/foo.py dans gui/bar.py via un from project.core.foo import ... ou from ..core.foo import ..., et autres dérivés.

@entwanne Visiblement mon cerveau tourne encore rond alors ^^. L’alimenter directement avec les décorateurs ? J’avoue ne pas trop voir l’intérêt (sachant qu’il ne bougera pas au fil de l’execution du programme), de plus le but d’avoir une doc c’est que ceux qui bossent sur l’interface et ceux sur les scripts puissent se mettre d’accord sans avoir besoin de poser pleins de questions. Mais je veux bien savoir quel serait l’intérêt en plus d’un truc statique :)

Ricocotam

L’intérêt c’est de ne pas devoir maintenir un fichier avec les références vers chaque fonction.

Dans l’idéal, tu donnes une archive avec le code source, mais si tu veux un exécutable tout intégré tu as pyfreeze et équivalent. Néanmoins cela embarque un interpréteur python et les dépendances de ton projet, donc ce n’est pas forcément l’idéal pour toutes les cibles.

J’ai déjà rencontrer ce problème, j’ai trouvé la fonction eval(). Concrètement:

1
2
3
4
from image import analysis
#func = eval('analysis.foo')
func = eval(file['analysis_foo'])
func(params)

Je sais pas si ça ce fait, mais ça marche.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte