Table of Contents

Interface python

Qu'est ce que c'est?

Python est un langage interprété (comme le shell unix, matlab, etc) qui ressemble un peu à l'interpréteur intégré dans Oofelie. Contrairement à ce dernier, il est très complet, rapide, orienté objet, utilisant le typage dynamique, interfaçable avec plus ou moins n'importe quoi. De plus, c'est maintenant une référence vu le nombre d'utilisateurs à travers le monde (scientifique ou non).

Pour moi, c'est LA solution idéale pour interfacer un code de calcul avec la ligne de commande.

Pour la petite histoire, Python a été inventé par Guido van Rossum en 1990 (c'est-à-dire plus ou moins quand Igor a inventé Oofelie). On peut dire que Python est ce que l'interpréteur Oofelie serait devenu si Igor avait continué à travailler dessus (et s'il avait trouvé quelques centaines de petites mains pour l'aider). Parmi les organisations qui utilisent Python, citons Google, Yahoo et RedHat. Parmi les codes EF, Code_Aster et Abaqus. N'oublions pas que VTK et Qt sont aussi interfacés avec Python.

Pour en savoir plus sur ce fabuleux langage (n'ayons pas peur des mots):

Python vs l'interpreteur Oofelie (OE)

Le combat est assez inégal, et perdu d'avance pour OE:

OE Python
Extensible via les I_, bon courage ! oui (classes interprétées, API C). extension possible via des scripts (on peut dériver une classe interprétée d'une classe compilée)
Modulaire non - pas de notion de package - conflits de noms fréquents namespaces (modules)
Rapide bof (pas de hashMap) oui (fichiers compilés, portables .pyc, hashMaps intégrées)
Gestion des erreurs peu fiable. Il a la mauvaise habitude de ne pas s'arrêter lorsque des erreurs surviennent rendant difficile la localisation de celles-ci. très fiable (exceptions - callstack). Impossible de louper une erreur de syntaxe.
Extensions absentes - à programmer soi même. réseau, MPI, graphisme (Tcl, Qt), système… - voir p.expl ce site
Syntaxe pas claire (cfr “;”) claire et fiable
Gestion mémoire absente ou catastrophique, au choix compteurs de refs - destructeurs - entièrement customisable
Portable bof - chaque nouvelle machine nécessite un portage fastidieux. oui - toute plateforme
Maintenance non négligeable (à chaque mise à jour) quasi nulle pour nous
Bugs nombreux (nombre croissant) - corrigés par nous très peu - corrigés par d'autres
Debugueur non oui, intégré
Licence payant (pas pour nous mais…) gratuit - même encore mieux: on peut le revendre! (voir licence python)

Ajoutons à ca des petits “plus” comme l'éditeur IDLE qui permet, avec son “path browser”, de parcourir toutes les fonctions et les modules disponibles. L'interface Tk intégrée à la distribution est aussi très intéressante.

En fait, tout ce qui peut se faire avec l'interpréteur Oofelie peut se faire avec Python. J'ai donc essayé de recréer un environnement “Oofelie” sous Python avec la contrainte d'une syntaxe similaire (ce n'est pas simple parce que l'interpréteur OE cache souvent beaucoup de choses à l'utilisateur - comme des conversions implicites).

Une application très simple de la puissance de Python serait de programmer l'ouverture d'une fenêtre lors du chargement d'un jeu de données pour que l'utilisateur puisse entrer, charger/sauver ses paramètres et enfin pousser sur le bouton “start metafor”. C'est fait en quelques lignes sous Python et ça permet de créer rapidement une application “métier”. Il est même possible, dans ce cas, de ne distribuer que le fichier .pyc (version compilée et indépendante de la plateforme du .py).

metapython.jpg

Parmi les nombreuses choses que nous avions demandé à OE et qui nous sont maintenant accessible, citons (dans le désordre) :

En un mot, on a d'un coup tout ce que Igor prétend faire pour la fin du mois dans sa présentation d'Oofelie :-)

Un exemple d'erreur (avec impression de la callstack):

  Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/d50/users/boman/dev/oo_meta/toolbox/utilities.py", line 7, in meta
  module = __import__(domainTxt, globals(), locals(), ['getDomain'])
  File "/d50/users/boman/dev/oo_meta/apps/zqs/ale_5cotes.py", line 144, in ?
  excit.define(1,NODE_PO,Key(TX|GD|RE),0.0000000000E+00,ale_5cotes_fct1,EX_INCR); fixaset.define(1,NODE_PO,Key(TX));
  NameError: name 'EX_INCR' is not defined

L'interface Python de Metafor

Python possède une API écrite en C qui permet d'écrire des “modules” (comme les packages en java, ou namespaces en C++). Metafor est donc un module de Python…. enfin, presque. En effet, n'oublions pas que grâce au magnifique travail d'Igor sur les matériaux et les éléments, il n'est pas possible d'initialiser correctement ceux-ci quand ils sont regroupés dans une lib. J'ai dû donc choisir d'intégrer Python dans l'exécutable Metafor.

Cette interface n'est pas simple à écrire parce que l'API Python est complexe. J'étais donc un peu découragé jusqu'au jour où j'ai vu le logiciel Swig (Simplified Wrapper and Interface Generator) qui se charge du boulot. Mieux encore, Swig crée des “shadow classes” qui permettent d'obtenir des objets Python malgré l'API écrite en C. Swig gère aussi tous les problèmes de cast (ce qui pose beaucoup de problèmes dans l'interpréteur Oofelie).

Swig n'est pas qu'un simple traducteur: il gère également la surcharge des fonctions membres (absentes dans Python puisque les types d'objets ne sont pas explicites) et l'héritage multiple. Tout ceci via un système de cast dynamique assez bien fait et relativement bien optimisé (j ai jeté un œil, c'est largement mieux fait que OE). Enfin, Swig gère correctement les variables globales (qui, elles, ne sont pas des références Python).

L'interface Python de Metafor se réduit donc à des fichiers input de Swig (fichiers .i et .swg). Les fichiers .i donnent des .cpp via Swig qui sont compilés un à un pour former des modules. Les fichiers .swg sont des fichiers inclus par les .i qui ne correspondent pas à un module. A l'heure actuelle, ces fichiers interfacent toutes les fonctions membres (publiques) des classes Metafor et Oofelie utilisées dans le célèbre cas-test “cont2”.

Lorsqu'on lance Metafor, on se retrouve en ligne de commande Python. Le module Metafor est déjà chargé en mémoire ainsi que le module utilitaire (toolbox.utilities). Il est donc possible de lancer un cas-test (myTest.py) par la simple commande:

  meta('myTest')

Contrairement à Oofelie, Python ne va pas commencer à parcourir les répertoires pour trouver myTest.py. J'ai pourtant reprogrammé cette fonction mais je trouve que c'est pas très intéressant vu les conflits possibles. J'ai donc choisi que pour lancer cont2.py, par exemple, qui se trouve dans oo_meta/apps/qs, on tape:

  meta('apps.qs.cont2')

c'est propre et net!

Qu'est ce qui m'a pris du temps si c'est si simple?

Avoir une première interface est très simple. Le premier problème était les cast implicites cachés derrière les get_properties(). Heureusement, Swig peut gérer ça facilement (un peu comme le I_::new_child_from_id() de OE). J'ai dû aussi gérer les std::string et les UserNo via des “typemaps” de Swig (un système qui permet de faire des casts implicites automatiques).

Après ceci, le premier résultat ne ressemblait pas trop à l'interpréteur Oofelie. Par exemple, les Locks étaient stockées dans une variable cvar. Il fallait donc écrire:

  loadingset.define(1,NODE_PO, Key(cvar.TX|cvar.GD|cvar.RE), 0, f)

ce qui est lourd. J'ai donc réussi à “descendre” les variables cvar dans chaque namespace (et ceci de manière automatique - sans écrire). Bref, si on ajoute une Lock, ça marche tout seul).

Même remarque pour les noms d'éléments, de matériaux, de Elementproperties, de MaterialProperties, identificateurs, etc.

Comment se mettre à Python?

Pour démarrer:

Différences par rapport à l'interpréteur OE: