1 // Copyright (C) 2006-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "RuntimeSALOME.hxx"
21 #include "PythonNode.hxx"
22 #include "PythonPorts.hxx"
23 #include "TypeCode.hxx"
24 #include "AutoGIL.hxx"
25 #include "Container.hxx"
26 #include "SalomeContainer.hxx"
27 #include "SalomeHPContainer.hxx"
28 #include "SalomeContainerTmpForHP.hxx"
29 #include "ConversionException.hxx"
31 #include "PyStdout.hxx"
38 #define getpid _getpid
41 #if PY_VERSION_HEX < 0x02050000
42 typedef int Py_ssize_t;
46 #include "YacsTrace.hxx"
48 using namespace YACS::ENGINE;
51 const char PythonNode::IMPL_NAME[]="Python";
52 const char PythonNode::KIND[]="Python";
54 PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father)
56 _implementation=IMPL_NAME;
59 _context=PyDict_New();
60 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
63 msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
64 _errorDetails=msg.str();
65 throw Exception(msg.str());
70 PythonNode::PythonNode(const std::string& name):InlineNode(name)
72 _implementation=IMPL_NAME;
75 _context=PyDict_New();
76 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
79 msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
80 _errorDetails=msg.str();
81 throw Exception(msg.str());
86 PythonNode::~PythonNode()
89 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
93 void PythonNode::checkBasicConsistency() const throw(YACS::Exception)
95 DEBTRACE("checkBasicConsistency");
96 InlineNode::checkBasicConsistency();
100 res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
103 std::string error="";
104 PyObject* new_stderr = newPyStdOut(error);
105 PySys_SetObject((char*)"stderr", new_stderr);
107 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
108 Py_DECREF(new_stderr);
109 throw Exception(error);
116 void PythonNode::load()
118 DEBTRACE( "---------------PyNode::load function---------------" );
125 void PythonNode::loadLocal()
127 DEBTRACE( "---------------PyNode::loadLocal function---------------" );
131 void PythonNode::loadRemote()
133 DEBTRACE( "---------------PyNode::loadRemote function---------------" );
134 bool isContAlreadyStarted(false);
137 isContAlreadyStarted=_container->isAlreadyStarted(this);
138 if(!isContAlreadyStarted)
142 _container->start(this);
146 _errorDetails=e.what();
153 std::string what("PyNode::loadRemote : a load operation requested on \"");
154 what+=_name; what+="\" with no container specified.";
156 throw Exception(what);
160 Engines::Container_var objContainer=Engines::Container::_nil();
162 throw Exception("No container specified !");
163 SalomeContainer *containerCast0(dynamic_cast<SalomeContainer *>(_container));
164 SalomeHPContainer *containerCast1(dynamic_cast<SalomeHPContainer *>(_container));
166 objContainer=containerCast0->getContainerPtr(this);
167 else if(containerCast1)
169 YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(containerCast1,this));
170 objContainer=tmpCont->getContainerPtr(this);
173 throw Exception("Unrecognized type of container ! Salome one is expected for PythonNode !");
174 if(CORBA::is_nil(objContainer))
175 throw Exception("Container corba pointer is NULL for PythonNode !");
176 bool isInitializeRequested(false);
181 _pynode = objContainer->createPyScriptNode(getName().c_str(),getScript().c_str());
185 Engines::PyScriptNode_var dftPyScript(objContainer->getDefaultPyScriptNode());
186 if(CORBA::is_nil(dftPyScript))
188 isInitializeRequested=true;
189 _pynode = objContainer->createPyScriptNode(getName().c_str(),getScript().c_str());
192 _pynode = dftPyScript;
195 catch( const SALOME::SALOME_Exception& ex )
197 std::string msg="Exception on remote python node creation ";
199 msg += ex.details.text.in();
201 throw Exception(msg);
204 if(CORBA::is_nil(_pynode))
205 throw Exception("In PythonNode the ref in NULL ! ");
210 const char picklizeScript[]="import cPickle\n"
211 "def pickleForDistPyth2009(kws):\n"
212 " return cPickle.dumps(((),kws),-1)\n"
214 "def unPickleForDistPyth2009(st):\n"
215 " args=cPickle.loads(st)\n"
217 PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context);
221 PyObject* new_stderr = newPyStdOut(_errorDetails);
222 PySys_SetObject((char*)"stderr", new_stderr);
224 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
225 Py_DECREF(new_stderr);
226 throw Exception("Error during load");
230 _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009");
231 _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009");
232 if(_pyfuncSer == NULL)
235 PyObject* new_stderr = newPyStdOut(_errorDetails);
236 PySys_SetObject((char*)"stderr", new_stderr);
238 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
239 Py_DECREF(new_stderr);
240 throw Exception("Error during load");
242 if(_pyfuncUnser == NULL)
245 PyObject* new_stderr = newPyStdOut(_errorDetails);
246 PySys_SetObject((char*)"stderr", new_stderr);
248 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
249 Py_DECREF(new_stderr);
250 throw Exception("Error during load");
252 if(isInitializeRequested)
253 {//This one is called only once at initialization in the container if an init-script is specified.
256 std::string zeInitScriptKey(_container->getProperty(HomogeneousPoolContainer::INITIALIZE_SCRIPT_KEY));
257 if(!zeInitScriptKey.empty())
258 _pynode->executeAnotherPieceOfCode(zeInitScriptKey.c_str());
260 catch( const SALOME::SALOME_Exception& ex )
262 std::string msg="Exception on PythonNode::loadRemote python invocation of initializisation py script !";
264 msg += ex.details.text.in();
266 throw Exception(msg);
269 DEBTRACE( "---------------End PyNode::loadRemote function---------------" );
273 void PythonNode::execute()
281 void PythonNode::executeRemote()
283 DEBTRACE( "++++++++++++++ PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
285 throw Exception("DistributedPythonNode badly loaded");
286 Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);
289 PyObject *args(0),*ob(0);
290 //===========================================================================
291 // Get inputs in input ports, build a Python dict and pickle it
292 //===========================================================================
294 std::list<InputPort *>::iterator iter2;
296 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); ++iter2)
298 InputPyPort *p=(InputPyPort *)*iter2;
300 PyDict_SetItemString(args,p->getName().c_str(),ob);
304 PyObject_Print(args,stderr,Py_PRINT_RAW);
307 PyObject *serializationInput(PyObject_CallFunctionObjArgs(_pyfuncSer,args,NULL));
309 //The pickled string may contain NULL characters so use PyString_AsStringAndSize
310 char *serializationInputC(0);
312 if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len))
313 throw Exception("DistributedPythonNode problem in python pickle");
314 serializationInputCorba->length(len);
315 for(int i=0; i < len ; i++)
316 serializationInputCorba[i]=serializationInputC[i];
317 Py_DECREF(serializationInput);
320 //get the list of output argument names
321 std::list<OutputPort *>::iterator iter;
322 Engines::listofstring myseq;
323 myseq.length(getNumberOfOutputPorts());
325 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
327 OutputPyPort *p=(OutputPyPort *)*iter;
328 myseq[pos]=p->getName().c_str();
329 DEBTRACE( "port name: " << p->getName() );
330 DEBTRACE( "port kind: " << p->edGetType()->kind() );
331 DEBTRACE( "port pos : " << pos );
334 //===========================================================================
335 // Execute in remote Python node
336 //===========================================================================
337 DEBTRACE( "-----------------starting remote python invocation-----------------" );
338 Engines::pickledArgs_var resultCorba;
341 //pass outargsname and dict serialized
342 resultCorba=_pynode->execute(myseq,serializationInputCorba);
344 catch( const SALOME::SALOME_Exception& ex )
346 std::string msg="Exception on remote python invocation";
348 msg += ex.details.text.in();
350 throw Exception(msg);
352 DEBTRACE( "-----------------end of remote python invocation-----------------" );
353 //===========================================================================
354 // Get results, unpickle and put them in output ports
355 //===========================================================================
356 char *resultCorbaC=new char[resultCorba->length()+1];
357 resultCorbaC[resultCorba->length()]='\0';
358 for(int i=0;i<resultCorba->length();i++)
359 resultCorbaC[i]=resultCorba[i];
363 PyObject *args(0),*ob(0);
364 PyObject* resultPython=PyString_FromStringAndSize(resultCorbaC,resultCorba->length());
365 delete [] resultCorbaC;
366 args = PyTuple_New(1);
367 PyTuple_SetItem(args,0,resultPython);
368 PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
371 if (finalResult == NULL)
373 std::stringstream msg;
374 msg << "Conversion with pickle of output ports failed !";
375 msg << " : " << __FILE__ << ":" << __LINE__;
376 _errorDetails=msg.str();
377 throw YACS::ENGINE::ConversionException(msg.str());
380 DEBTRACE( "-----------------PythonNode::outputs-----------------" );
382 if(finalResult == Py_None)
384 else if(PyTuple_Check(finalResult))
385 nres=PyTuple_Size(finalResult);
387 if(getNumberOfOutputPorts() != nres)
389 std::string msg="Number of output arguments : Mismatch between definition and execution";
390 Py_DECREF(finalResult);
392 throw Exception(msg);
398 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
400 OutputPyPort *p=(OutputPyPort *)*iter;
401 DEBTRACE( "port name: " << p->getName() );
402 DEBTRACE( "port kind: " << p->edGetType()->kind() );
403 DEBTRACE( "port pos : " << pos );
404 if(PyTuple_Check(finalResult))
405 ob=PyTuple_GetItem(finalResult,pos) ;
408 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
412 Py_DECREF(finalResult);
414 catch(ConversionException& ex)
416 Py_DECREF(finalResult);
417 _errorDetails=ex.what();
421 DEBTRACE( "++++++++++++++ ENDOF PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
424 void PythonNode::executeLocal()
426 DEBTRACE( "++++++++++++++ PyNode::executeLocal: " << getName() << " ++++++++++++++++++++" );
430 DEBTRACE( "---------------PyNode::inputs---------------" );
431 list<InputPort *>::iterator iter2;
432 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
434 InputPyPort *p=(InputPyPort *)*iter2;
435 DEBTRACE( "port name: " << p->getName() );
436 DEBTRACE( "port kind: " << p->edGetType()->kind() );
437 PyObject* ob=p->getPyObj();
438 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
440 PyObject_Print(ob,stderr,Py_PRINT_RAW);
443 int ier=PyDict_SetItemString(_context,p->getName().c_str(),ob);
444 DEBTRACE( "after PyDict_SetItemString:ob refcnt: " << ob->ob_refcnt );
447 DEBTRACE( "---------------End PyNode::inputs---------------" );
450 DEBTRACE( "----------------PyNode::calculation---------------" );
452 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
454 std::ostringstream stream;
455 stream << "/tmp/PythonNode_";
458 PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
462 PyObject* new_stderr = newPyStdOut(_errorDetails);
463 PySys_SetObject((char*)"stderr", new_stderr);
465 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
466 Py_DECREF(new_stderr);
467 throw Exception("Error during execution");
469 PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context);
473 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
476 if(PyErr_Occurred ())
479 PyObject* new_stderr = newPyStdOut(_errorDetails);
480 PySys_SetObject((char*)"stderr", new_stderr);
481 ofstream errorfile(stream.str().c_str());
482 if (errorfile.is_open())
484 errorfile << _script;
488 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
489 Py_DECREF(new_stderr);
490 throw Exception("Error during execution");
493 DEBTRACE( "-----------------PyNode::outputs-----------------" );
494 list<OutputPort *>::iterator iter;
497 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
499 OutputPyPort *p=(OutputPyPort *)*iter;
500 DEBTRACE( "port name: " << p->getName() );
501 DEBTRACE( "port kind: " << p->edGetType()->kind() );
502 PyObject *ob=PyDict_GetItemString(_context,p->getName().c_str());
505 std::string msg="Error during execution: there is no variable ";
506 msg=msg+p->getName()+" in node context";
508 throw Exception(msg);
510 DEBTRACE( "PyNode::outputs::ob refcnt: " << ob->ob_refcnt );
512 PyObject_Print(ob,stderr,Py_PRINT_RAW);
518 catch(ConversionException& ex)
520 _errorDetails=ex.what();
524 DEBTRACE( "-----------------End PyNode::outputs-----------------" );
526 DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" );
529 std::string PythonNode::getContainerLog()
531 if(_mode=="local")return "";
536 Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(this);
537 CORBA::String_var logname = objContainer->logfilename();
540 std::string::size_type pos = msg.find(":");
541 msg=msg.substr(pos+1);
545 msg = "Container no longer reachable";
550 void PythonNode::shutdown(int level)
552 DEBTRACE("PythonNode::shutdown " << level);
553 if(_mode=="local")return;
556 if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
557 _pynode=Engines::PyScriptNode::_nil();
558 _container->shutdown(level);
562 Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
564 return new PythonNode(*this,father);
567 //! Create a new node of same type with a given name
568 PythonNode* PythonNode::cloneNode(const std::string& name)
570 PythonNode* n=new PythonNode(name);
571 n->setScript(_script);
572 list<InputPort *>::iterator iter;
573 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
575 InputPyPort *p=(InputPyPort *)*iter;
576 DEBTRACE( "port name: " << p->getName() );
577 DEBTRACE( "port kind: " << p->edGetType()->kind() );
578 n->edAddInputPort(p->getName(),p->edGetType());
580 list<OutputPort *>::iterator iter2;
581 for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
583 OutputPyPort *p=(OutputPyPort *)*iter2;
584 DEBTRACE( "port name: " << p->getName() );
585 DEBTRACE( "port kind: " << p->edGetType()->kind() );
586 n->edAddOutputPort(p->getName(),p->edGetType());
591 PyFuncNode::PyFuncNode(const PyFuncNode& other, ComposedNode *father):InlineFuncNode(other,father),_pyfunc(0)
593 _implementation = PythonNode::IMPL_NAME;
596 _context=PyDict_New();
597 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
598 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
601 msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
602 _errorDetails=msg.str();
603 throw Exception(msg.str());
608 PyFuncNode::PyFuncNode(const std::string& name): InlineFuncNode(name),_pyfunc(0)
611 _implementation = PythonNode::IMPL_NAME;
612 DEBTRACE( "PyFuncNode::PyFuncNode " << name );
615 _context=PyDict_New();
616 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
617 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
620 msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
621 _errorDetails=msg.str();
622 throw Exception(msg.str());
627 PyFuncNode::~PyFuncNode()
629 DEBTRACE( getName() );
632 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
633 if(_pyfunc)DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
636 if(!CORBA::is_nil(_pynode))
638 _pynode->UnRegister();
642 void PyFuncNode::checkBasicConsistency() const throw(YACS::Exception)
644 DEBTRACE("checkBasicConsistency");
645 InlineFuncNode::checkBasicConsistency();
649 res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
652 std::string error="";
653 PyObject* new_stderr = newPyStdOut(error);
654 PySys_SetObject((char*)"stderr", new_stderr);
656 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
657 Py_DECREF(new_stderr);
658 throw Exception(error);
665 void PyFuncNode::load()
667 DEBTRACE( "---------------PyfuncNode::load function---------------" );
674 void PyFuncNode::loadRemote()
676 DEBTRACE( "---------------PyfuncNode::loadRemote function---------------" );
677 bool isContAlreadyStarted(false);
680 isContAlreadyStarted=_container->isAlreadyStarted(this);
681 if(!isContAlreadyStarted)
685 _container->start(this);
689 _errorDetails=e.what();
696 std::string what("PyFuncNode::loadRemote : a load operation requested on \"");
697 what+=_name; what+="\" with no container specified.";
699 throw Exception(what);
702 Engines::Container_var objContainer=Engines::Container::_nil();
704 throw Exception("No container specified !");
705 SalomeContainer *containerCast0(dynamic_cast<SalomeContainer *>(_container));
706 SalomeHPContainer *containerCast1(dynamic_cast<SalomeHPContainer *>(_container));
708 objContainer=containerCast0->getContainerPtr(this);
709 else if(containerCast1)
711 YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(containerCast1,this));
712 objContainer=tmpCont->getContainerPtr(this);
715 throw Exception("Unrecognized type of container ! Salome one is expected ! In PythonNode !");
716 if(CORBA::is_nil(objContainer))
717 throw Exception("Container corba pointer is NULL ! In PythonNode !");
718 bool isInitializeRequested(false);
723 _pynode = objContainer->createPyNode(getName().c_str(),getScript().c_str());
727 Engines::PyNode_var dftPyScript(objContainer->getDefaultPyNode());
728 if(CORBA::is_nil(dftPyScript))
730 isInitializeRequested=true;
731 _pynode = objContainer->createPyNode(getName().c_str(),getScript().c_str());
734 _pynode = dftPyScript;
737 catch( const SALOME::SALOME_Exception& ex )
739 std::string msg="Exception on remote python node creation ";
741 msg += ex.details.text.in();
743 throw Exception(msg);
746 if(CORBA::is_nil(_pynode))
747 throw Exception("In PyFuncNode the ref in NULL ! ");
751 const char picklizeScript[]="import cPickle\n"
752 "def pickleForDistPyth2009(*args,**kws):\n"
753 " return cPickle.dumps((args,kws),-1)\n"
755 "def unPickleForDistPyth2009(st):\n"
756 " args=cPickle.loads(st)\n"
758 PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context);
762 PyObject* new_stderr = newPyStdOut(_errorDetails);
763 PySys_SetObject((char*)"stderr", new_stderr);
765 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
766 Py_DECREF(new_stderr);
767 throw Exception("Error during load");
771 _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009");
772 _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009");
773 if(_pyfuncSer == NULL)
776 PyObject* new_stderr = newPyStdOut(_errorDetails);
777 PySys_SetObject((char*)"stderr", new_stderr);
779 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
780 Py_DECREF(new_stderr);
781 throw Exception("Error during load");
783 if(_pyfuncUnser == NULL)
786 PyObject* new_stderr = newPyStdOut(_errorDetails);
787 PySys_SetObject((char*)"stderr", new_stderr);
789 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
790 Py_DECREF(new_stderr);
791 throw Exception("Error during load");
793 if(isInitializeRequested)
794 {//This one is called only once at initialization in the container if an init-script is specified.
797 std::string zeInitScriptKey(_container->getProperty(HomogeneousPoolContainer::INITIALIZE_SCRIPT_KEY));
798 if(!zeInitScriptKey.empty())
799 _pynode->executeAnotherPieceOfCode(zeInitScriptKey.c_str());
801 catch( const SALOME::SALOME_Exception& ex )
803 std::string msg="Exception on PythonNode::loadRemote python invocation of initializisation py script !";
805 msg += ex.details.text.in();
807 throw Exception(msg);
810 DEBTRACE( "---------------End PyfuncNode::loadRemote function---------------" );
814 void PyFuncNode::loadLocal()
816 DEBTRACE( "---------------PyFuncNode::load function " << getName() << " ---------------" );
820 list<OutputPort *>::iterator iter;
821 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
823 OutputPyPort *p=(OutputPyPort *)*iter;
824 DEBTRACE( "port name: " << p->getName() );
825 DEBTRACE( "port kind: " << p->edGetType()->kind() );
831 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
833 std::ostringstream stream;
834 stream << "/tmp/PythonNode_";
837 PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
841 PyObject* new_stderr = newPyStdOut(_errorDetails);
842 PySys_SetObject((char*)"stderr", new_stderr);
844 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
845 Py_DECREF(new_stderr);
846 throw Exception("Error during execution");
848 PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context);
852 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
853 if(PyErr_Occurred ())
856 PyObject* new_stderr = newPyStdOut(_errorDetails);
857 PySys_SetObject((char*)"stderr", new_stderr);
858 ofstream errorfile(stream.str().c_str());
859 if (errorfile.is_open())
861 errorfile << _script;
865 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
866 Py_DECREF(new_stderr);
867 throw Exception("Error during execution");
870 _pyfunc=PyDict_GetItemString(_context,_fname.c_str());
871 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
875 PyObject* new_stderr = newPyStdOut(_errorDetails);
876 PySys_SetObject((char*)"stderr", new_stderr);
878 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
879 Py_DECREF(new_stderr);
880 throw Exception("Error during execution");
882 DEBTRACE( "---------------End PyFuncNode::load function---------------" );
886 void PyFuncNode::execute()
894 void PyFuncNode::executeRemote()
896 DEBTRACE( "++++++++++++++ PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
898 throw Exception("DistributedPythonNode badly loaded");
899 Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);;
903 //===========================================================================
904 // Get inputs in input ports, build a Python tuple and pickle it
905 //===========================================================================
906 PyObject *args(PyTuple_New(getNumberOfInputPorts()));
908 for(std::list<InputPort *>::iterator iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++,pos++)
910 InputPyPort *p=(InputPyPort *)*iter2;
913 PyTuple_SetItem(args,pos,ob);
916 PyObject_Print(args,stderr,Py_PRINT_RAW);
919 PyObject *serializationInput=PyObject_CallObject(_pyfuncSer,args);
921 //The pickled string may contain NULL characters so use PyString_AsStringAndSize
922 char *serializationInputC(0);
924 if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len))
925 throw Exception("DistributedPythonNode problem in python pickle");
927 serializationInputCorba->length(len);
928 for(int i=0; i < len ; i++)
929 serializationInputCorba[i]=serializationInputC[i];
930 Py_DECREF(serializationInput);
933 //===========================================================================
934 // Execute in remote Python node
935 //===========================================================================
936 DEBTRACE( "-----------------starting remote python invocation-----------------" );
937 Engines::pickledArgs_var resultCorba;
940 resultCorba=_pynode->execute(getFname().c_str(),serializationInputCorba);
942 catch( const SALOME::SALOME_Exception& ex )
944 std::string msg="Exception on remote python invocation";
946 msg += ex.details.text.in();
948 throw Exception(msg);
950 DEBTRACE( "-----------------end of remote python invocation-----------------" );
951 //===========================================================================
952 // Get results, unpickle and put them in output ports
953 //===========================================================================
954 char *resultCorbaC=new char[resultCorba->length()+1];
955 resultCorbaC[resultCorba->length()]='\0';
956 for(int i=0;i<resultCorba->length();i++)
957 resultCorbaC[i]=resultCorba[i];
962 PyObject *resultPython(PyString_FromStringAndSize(resultCorbaC,resultCorba->length()));
963 delete [] resultCorbaC;
964 PyObject *args(PyTuple_New(1)),*ob(0);
965 PyTuple_SetItem(args,0,resultPython);
966 PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
969 DEBTRACE( "-----------------PythonNode::outputs-----------------" );
971 if(finalResult == Py_None)
973 else if(PyTuple_Check(finalResult))
974 nres=PyTuple_Size(finalResult);
976 if(getNumberOfOutputPorts() != nres)
978 std::string msg="Number of output arguments : Mismatch between definition and execution";
979 Py_DECREF(finalResult);
981 throw Exception(msg);
987 for(std::list<OutputPort *>::iterator iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++, pos++)
989 OutputPyPort *p=(OutputPyPort *)*iter;
990 DEBTRACE( "port name: " << p->getName() );
991 DEBTRACE( "port kind: " << p->edGetType()->kind() );
992 DEBTRACE( "port pos : " << pos );
993 if(PyTuple_Check(finalResult))
994 ob=PyTuple_GetItem(finalResult,pos) ;
997 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1000 Py_DECREF(finalResult);
1002 catch(ConversionException& ex)
1004 Py_DECREF(finalResult);
1005 _errorDetails=ex.what();
1010 DEBTRACE( "++++++++++++++ ENDOF PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
1013 void PyFuncNode::executeLocal()
1015 DEBTRACE( "++++++++++++++ PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
1019 if(!_pyfunc)throw Exception("PyFuncNode badly loaded");
1022 DEBTRACE( "---------------PyFuncNode::inputs---------------" );
1023 PyObject* args = PyTuple_New(getNumberOfInputPorts()) ;
1024 list<InputPort *>::iterator iter2;
1025 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
1027 InputPyPort *p=(InputPyPort *)*iter2;
1028 DEBTRACE( "port name: " << p->getName() );
1029 DEBTRACE( "port kind: " << p->edGetType()->kind() );
1032 PyObject_Print(ob,stderr,Py_PRINT_RAW);
1035 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1037 PyTuple_SetItem(args,pos,ob);
1038 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1041 DEBTRACE( "---------------End PyFuncNode::inputs---------------" );
1043 DEBTRACE( "----------------PyFuncNode::calculation---------------" );
1045 PyObject_Print(_pyfunc,stderr,Py_PRINT_RAW);
1047 PyObject_Print(args,stderr,Py_PRINT_RAW);
1050 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
1051 PyObject* result = PyObject_CallObject( _pyfunc , args ) ;
1052 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
1059 PyObject* new_stderr = newPyStdOut(_errorDetails);
1060 PySys_SetObject((char*)"stderr", new_stderr);
1061 std::ostringstream stream;
1062 stream << "/tmp/PythonNode_";
1064 ofstream errorfile(stream.str().c_str());
1065 if (errorfile.is_open())
1067 errorfile << _script;
1071 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
1072 Py_DECREF(new_stderr);
1073 throw Exception("Error during execution");
1075 DEBTRACE( "----------------End PyFuncNode::calculation---------------" );
1077 DEBTRACE( "-----------------PyFuncNode::outputs-----------------" );
1079 if(result == Py_None)
1081 else if(PyTuple_Check(result))
1082 nres=PyTuple_Size(result);
1084 if(getNumberOfOutputPorts() != nres)
1086 std::string msg="Number of output arguments : Mismatch between definition and execution";
1089 throw Exception(msg);
1094 PyObject_Print(result,stderr,Py_PRINT_RAW);
1097 list<OutputPort *>::iterator iter;
1100 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
1102 OutputPyPort *p=(OutputPyPort *)*iter;
1103 DEBTRACE( "port name: " << p->getName() );
1104 DEBTRACE( "port kind: " << p->edGetType()->kind() );
1105 DEBTRACE( "port pos : " << pos );
1106 if(PyTuple_Check(result))ob=PyTuple_GetItem(result,pos) ;
1108 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1110 PyObject_Print(ob,stderr,Py_PRINT_RAW);
1117 catch(ConversionException& ex)
1120 _errorDetails=ex.what();
1123 DEBTRACE( "-----------------End PyFuncNode::outputs-----------------" );
1126 DEBTRACE( "++++++++++++++ End PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
1129 Node *PyFuncNode::simpleClone(ComposedNode *father, bool editionOnly) const
1131 return new PyFuncNode(*this,father);
1134 //! Create a new node of same type with a given name
1135 PyFuncNode* PyFuncNode::cloneNode(const std::string& name)
1137 PyFuncNode* n=new PyFuncNode(name);
1138 n->setScript(_script);
1139 n->setFname(_fname);
1140 list<InputPort *>::iterator iter;
1141 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
1143 InputPyPort *p=(InputPyPort *)*iter;
1144 n->edAddInputPort(p->getName(),p->edGetType());
1146 list<OutputPort *>::iterator iter2;
1147 for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
1149 OutputPyPort *p=(OutputPyPort *)*iter2;
1150 n->edAddOutputPort(p->getName(),p->edGetType());
1155 std::string PyFuncNode::getContainerLog()
1157 if(_mode=="local")return "";
1162 Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(this);
1163 CORBA::String_var logname = objContainer->logfilename();
1166 std::string::size_type pos = msg.find(":");
1167 msg=msg.substr(pos+1);
1171 msg = "Container no longer reachable";
1176 void PyFuncNode::shutdown(int level)
1178 DEBTRACE("PyFuncNode::shutdown " << level);
1179 if(_mode=="local")return;
1182 if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
1183 _pynode=Engines::PyNode::_nil();
1184 _container->shutdown(level);