4 Utilisation avancée de l'interface de programmation Python
5 ==========================================================================
7 Passage d'objets Python entre noeuds de calcul
8 --------------------------------------------------
9 Le modèle de données standard de YACS permet d'échanger un certain nombre de types
10 de données (voir :ref:`datatypes`) qui sont limités aux types supportés par CORBA.
11 Le langage Python permet de manipuler des types de données qui ne sont pas gérés par YACS.
12 En particulier, le dictionnaire Python avec des types de données hétérogènes n'est pas géré
13 par le modèle de données de YACS.
15 Il est cependant possible d'échanger des dictionnaires python entre certains types de noeuds de calcul
16 en utilisant des références d'objets avec un protocole non standard. Le protocole standard est
17 le protocole IDL qui correspond à une sérialisation des données gérée par CORBA.
18 Il existe deux autres protocoles (python et json) qui utilisent des mécanismes de sérialisation
19 non CORBA qui supportent plus de types de données dont les dictionnaires.
20 Le nom du protocole apparait dans la première partie du Repositiory ID du type (avant le premier :).
23 ++++++++++++++++++++++
24 Le protocole python s'appuie sur une sérialisation faite par le module cPickle (implémentation C
26 Il suffit de définir un type référence d'objet avec le protocole python pour pouvoir échanger
27 des objets python entre noeuds inline python et avec des composants SALOME implémentés en python.
28 Les composants SALOME implémentés en python qui veulent supporter ce type d'échange doivent être
29 conçus pour recevoir une chaine de caractères qui contient l'objet sérialisé. La désérialisation
30 de l'objet reste à la charge du composant. Dans l'autre sens, la sérialisation est à la charge
31 du composant qui doit retourner une chaine de caractères pour ce type d'objet.
33 Définition du type "objet python"::
35 tc1=p.createInterfaceTc("python:obj:1.0","PyObj",[])
37 Définition de deux noeuds Python qui utilisent ce type::
39 n2=r.createScriptNode("","node2")
42 p1={'a':1,'b':5.6,'c':[1,2,3]}
44 n2.edAddOutputPort("p1",tc1)
46 n3=r.createScriptNode("","node3")
50 n3.edAddInputPort("p1",tc1)
52 p.edAddDFLink(n2.getOutputPort("p1"),n3.getInputPort("p1"))
54 Définition d'un noeud de service SALOME qui utilise ce type::
56 n1=r.createCompoNode("","node1")
59 n1.edAddInputPort("p1",tc1)
60 n1.edAddOutputPort("p1",tc1)
62 p.edAddDFLink(n2.getOutputPort("p1"),n1.getInputPort("p1"))
64 L'implémentation du composant compo1 doit prendre en charge la sérialisation/désérialisation
65 comme dans l'exemple de la méthode run qui suit::
69 ret={'a':6, 'b':[1,2,3]}
70 return cPickle.dumps(ret,-1)
73 ++++++++++++++++++++++
74 Le protocole json s'appuie sur la sérialisation/désérialisation `JSON <http://www.json.org/>`_
75 (JavaScript Object Notation) à la place de cPickle. json supporte moins de types de données
76 et nécessite l'installation du module python simplejson mais il a l'avantage d'être
77 plus interopérable. En particulier, il existe des librairies C++ qui sérialisent/désérialisent
80 Pour utiliser ce protocole dans YACS, il suffit de remplacer python par json dans la définition
81 du type. Par exemple::
83 tc1=p.createInterfaceTc("json:obj:1.0","PyObj",[])
85 Le reste est identique sauf l'implémentation du composant qui devient en reprenant l'exemple
90 ret={'a':6, 'b':[1,2,3]}
91 return simplejson.dumps(ret)
93 Définition de composants Python inline
94 --------------------------------------------------
95 Normalement, un composant SALOME Python doit être développé en dehors de YACS soit
96 à la main soit en utilisant un générateur de module SALOME comme :ref:`yacsgen`.
97 Il est possible de définir un composant SALOME implémenté en Python directement
98 dans un script python. Ce type de composant peut être utile dans les phases de test,
101 La première étape consiste à compiler l'interface IDL directement dans le script python
102 ce qui a pour effet de créer les modules Python CORBA nécessaires. Par exemple, voici
103 comment on produit les modules CORBA compo1 et compo1__POA qui contiennent l'interface
104 base avec une seule méthode run::
107 #include "DSC_Engines.idl"
108 #include "SALOME_Exception.idl"
110 interface base :Engines::Superv_Component {
111 string run(in string s) raises (SALOME::SALOME_Exception);
115 m=omniORB.importIDLString(idlcompo,["-I/local/chris/SALOME2/RELEASES/Install/KERNEL_V4_0/idl/salome"])
117 La deuxième étape consiste à définir le corps du composant compo1 et donc de sa méthode run.
119 Voici un exemple de définition faite dans le corps du script Python::
124 class compo(compo1__POA.base,dsccalcium.PyDSCComponent):
126 print "+++++++++++run+++++++++++",s
131 Ce qui est important ici, c'est que SALOME trouve dans le module compo1, la classe de même nom
132 qui représente le composant (d'où la dernière ligne).
134 La troisième étape consiste à définir un container SALOME local au script car ce composant n'a
135 d'existence que dans le script. La définition d'un container de nom "MyContainerPy" se fera
138 from omniORB import CORBA
139 from SALOME_ContainerPy import SALOME_ContainerPy_i
140 orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)
141 poa = orb.resolve_initial_references("RootPOA")
142 poaManager = poa._get_the_POAManager()
143 poaManager.activate()
144 cpy_i = SALOME_ContainerPy_i(orb, poa, "MyContainerPy")
146 en prenant bien garde à activer CORBA avec poaManager.activate().
148 Ensuite, il ne reste plus qu'à créer un container YACS et à y placer un noeud SALOME
149 comme pour un composant standard.