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 const char PythonNode::SCRIPT_FOR_SERIALIZATION[]="import cPickle\n"
55 "def pickleForDistPyth2009(kws):\n"
56 " return cPickle.dumps(((),kws),-1)\n"
58 "def unPickleForDistPyth2009(st):\n"
59 " args=cPickle.loads(st)\n"
62 const char PyFuncNode::SCRIPT_FOR_SERIALIZATION[]="import cPickle\n"
63 "def pickleForDistPyth2009(*args,**kws):\n"
64 " return cPickle.dumps((args,kws),-1)\n"
66 "def unPickleForDistPyth2009(st):\n"
67 " args=cPickle.loads(st)\n"
70 PythonEntry::PythonEntry():_context(0),_pyfuncSer(0),_pyfuncUnser(0)
74 PythonEntry::~PythonEntry()
77 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
78 // not Py_XDECREF of _pyfuncUnser because it is returned by PyDict_GetItem -> borrowed
79 // not Py_XDECREF of _pyfuncSer because it is returned by PyDict_GetItem -> borrowed
83 void PythonEntry::commonRemoteLoadPart1(InlineNode *reqNode)
85 DEBTRACE( "---------------PythonEntry::CommonRemoteLoad function---------------" );
86 Container *container(reqNode->getContainer());
87 bool isContAlreadyStarted(false);
90 isContAlreadyStarted=container->isAlreadyStarted(reqNode);
91 if(!isContAlreadyStarted)
95 container->start(reqNode);
99 reqNode->setErrorDetails(e.what());
106 std::string what("PythonEntry::CommonRemoteLoad : a load operation requested on \"");
107 what+=reqNode->getName(); what+="\" with no container specified.";
108 reqNode->setErrorDetails(what);
109 throw Exception(what);
113 Engines::Container_var PythonEntry::commonRemoteLoadPart2(InlineNode *reqNode, bool& isInitializeRequested)
115 Container *container(reqNode->getContainer());
116 Engines::Container_var objContainer=Engines::Container::_nil();
118 throw Exception("No container specified !");
119 SalomeContainer *containerCast0(dynamic_cast<SalomeContainer *>(container));
120 SalomeHPContainer *containerCast1(dynamic_cast<SalomeHPContainer *>(container));
122 objContainer=containerCast0->getContainerPtr(reqNode);
123 else if(containerCast1)
125 YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(containerCast1,reqNode));
126 objContainer=tmpCont->getContainerPtr(reqNode);
129 throw Exception("Unrecognized type of container ! Salome one is expected for PythonNode/PyFuncNode !");
130 if(CORBA::is_nil(objContainer))
131 throw Exception("Container corba pointer is NULL for PythonNode !");
132 isInitializeRequested=false;
137 createRemoteAdaptedPyInterpretor(objContainer);
141 Engines::PyNodeBase_var dftPyScript(retrieveDftRemotePyInterpretorIfAny(objContainer));
142 if(CORBA::is_nil(dftPyScript))
144 isInitializeRequested=true;
145 createRemoteAdaptedPyInterpretor(objContainer);
148 assignRemotePyInterpretor(dftPyScript);
151 catch( const SALOME::SALOME_Exception& ex )
153 std::string msg="Exception on remote python node creation ";
155 msg += ex.details.text.in();
156 reqNode->setErrorDetails(msg);
157 throw Exception(msg);
159 Engines::PyNodeBase_var pynode(getRemoteInterpreterHandle());
160 if(CORBA::is_nil(pynode))
161 throw Exception("In PythonNode the ref in NULL ! ");
165 void PythonEntry::commonRemoteLoadPart3(InlineNode *reqNode, Engines::Container_ptr objContainer, bool isInitializeRequested)
167 Container *container(reqNode->getContainer());
168 Engines::PyNodeBase_var pynode(getRemoteInterpreterHandle());
172 const char *picklizeScript(getSerializationScript());
173 PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context);
176 std::string errorDetails;
177 PyObject* new_stderr = newPyStdOut(errorDetails);
178 reqNode->setErrorDetails(errorDetails);
179 PySys_SetObject((char*)"stderr", new_stderr);
181 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
182 Py_DECREF(new_stderr);
183 throw Exception("Error during load");
186 _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009");
187 _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009");
188 if(_pyfuncSer == NULL)
190 std::string errorDetails;
191 PyObject *new_stderr(newPyStdOut(errorDetails));
192 reqNode->setErrorDetails(errorDetails);
193 PySys_SetObject((char*)"stderr", new_stderr);
195 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
196 Py_DECREF(new_stderr);
197 throw Exception("Error during load");
199 if(_pyfuncUnser == NULL)
201 std::string errorDetails;
202 PyObject *new_stderr(newPyStdOut(errorDetails));
203 reqNode->setErrorDetails(errorDetails);
204 PySys_SetObject((char*)"stderr", new_stderr);
206 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
207 Py_DECREF(new_stderr);
208 throw Exception("Error during load");
211 if(isInitializeRequested)
212 {//This one is called only once at initialization in the container if an init-script is specified.
215 std::string zeInitScriptKey(container->getProperty(HomogeneousPoolContainer::INITIALIZE_SCRIPT_KEY));
216 if(!zeInitScriptKey.empty())
217 pynode->executeAnotherPieceOfCode(zeInitScriptKey.c_str());
219 catch( const SALOME::SALOME_Exception& ex )
221 std::string msg="Exception on PythonNode::loadRemote python invocation of initializisation py script !";
223 msg += ex.details.text.in();
224 reqNode->setErrorDetails(msg);
225 throw Exception(msg);
227 DEBTRACE( "---------------End PyNode::loadRemote function---------------" );
231 void PythonEntry::commonRemoteLoad(InlineNode *reqNode)
233 commonRemoteLoadPart1(reqNode);
234 bool isInitializeRequested;
235 Engines::Container_var objContainer(commonRemoteLoadPart2(reqNode,isInitializeRequested));
236 commonRemoteLoadPart3(reqNode,objContainer,isInitializeRequested);
239 PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father)
241 _implementation=IMPL_NAME;
244 _context=PyDict_New();
245 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
248 msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
249 _errorDetails=msg.str();
250 throw Exception(msg.str());
255 PythonNode::PythonNode(const std::string& name):InlineNode(name)
257 _implementation=IMPL_NAME;
260 _context=PyDict_New();
261 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
264 msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
265 _errorDetails=msg.str();
266 throw Exception(msg.str());
271 PythonNode::~PythonNode()
273 if(!CORBA::is_nil(_pynode))
275 _pynode->UnRegister();
279 void PythonNode::checkBasicConsistency() const throw(YACS::Exception)
281 DEBTRACE("checkBasicConsistency");
282 InlineNode::checkBasicConsistency();
286 res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
289 std::string error="";
290 PyObject* new_stderr = newPyStdOut(error);
291 PySys_SetObject((char*)"stderr", new_stderr);
293 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
294 Py_DECREF(new_stderr);
295 throw Exception(error);
302 void PythonNode::load()
304 DEBTRACE( "---------------PyNode::load function---------------" );
311 void PythonNode::loadLocal()
313 DEBTRACE( "---------------PyNode::loadLocal function---------------" );
317 void PythonNode::loadRemote()
319 commonRemoteLoad(this);
322 void PythonNode::execute()
330 void PythonNode::executeRemote()
332 DEBTRACE( "++++++++++++++ PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
334 throw Exception("DistributedPythonNode badly loaded");
336 if(dynamic_cast<HomogeneousPoolContainer *>(getContainer()))
339 commonRemoteLoadPart2(this,dummy);
340 _pynode->assignNewCompiledCode(getScript().c_str());
343 Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);
346 PyObject *args(0),*ob(0);
347 //===========================================================================
348 // Get inputs in input ports, build a Python dict and pickle it
349 //===========================================================================
351 std::list<InputPort *>::iterator iter2;
353 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); ++iter2)
355 InputPyPort *p=(InputPyPort *)*iter2;
357 PyDict_SetItemString(args,p->getName().c_str(),ob);
361 PyObject_Print(args,stderr,Py_PRINT_RAW);
364 PyObject *serializationInput(PyObject_CallFunctionObjArgs(_pyfuncSer,args,NULL));
366 //The pickled string may contain NULL characters so use PyString_AsStringAndSize
367 char *serializationInputC(0);
369 if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len))
370 throw Exception("DistributedPythonNode problem in python pickle");
371 serializationInputCorba->length(len);
372 for(int i=0; i < len ; i++)
373 serializationInputCorba[i]=serializationInputC[i];
374 Py_DECREF(serializationInput);
377 //get the list of output argument names
378 std::list<OutputPort *>::iterator iter;
379 Engines::listofstring myseq;
380 myseq.length(getNumberOfOutputPorts());
382 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
384 OutputPyPort *p=(OutputPyPort *)*iter;
385 myseq[pos]=p->getName().c_str();
386 DEBTRACE( "port name: " << p->getName() );
387 DEBTRACE( "port kind: " << p->edGetType()->kind() );
388 DEBTRACE( "port pos : " << pos );
391 //===========================================================================
392 // Execute in remote Python node
393 //===========================================================================
394 DEBTRACE( "-----------------starting remote python invocation-----------------" );
395 Engines::pickledArgs_var resultCorba;
398 //pass outargsname and dict serialized
399 resultCorba=_pynode->execute(myseq,serializationInputCorba);
401 catch( const SALOME::SALOME_Exception& ex )
403 std::string msg="Exception on remote python invocation";
405 msg += ex.details.text.in();
407 throw Exception(msg);
409 DEBTRACE( "-----------------end of remote python invocation-----------------" );
410 //===========================================================================
411 // Get results, unpickle and put them in output ports
412 //===========================================================================
413 char *resultCorbaC=new char[resultCorba->length()+1];
414 resultCorbaC[resultCorba->length()]='\0';
415 for(int i=0;i<resultCorba->length();i++)
416 resultCorbaC[i]=resultCorba[i];
420 PyObject *args(0),*ob(0);
421 PyObject* resultPython=PyString_FromStringAndSize(resultCorbaC,resultCorba->length());
422 delete [] resultCorbaC;
423 args = PyTuple_New(1);
424 PyTuple_SetItem(args,0,resultPython);
425 PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
428 if (finalResult == NULL)
430 std::stringstream msg;
431 msg << "Conversion with pickle of output ports failed !";
432 msg << " : " << __FILE__ << ":" << __LINE__;
433 _errorDetails=msg.str();
434 throw YACS::ENGINE::ConversionException(msg.str());
437 DEBTRACE( "-----------------PythonNode::outputs-----------------" );
439 if(finalResult == Py_None)
441 else if(PyTuple_Check(finalResult))
442 nres=PyTuple_Size(finalResult);
444 if(getNumberOfOutputPorts() != nres)
446 std::string msg="Number of output arguments : Mismatch between definition and execution";
447 Py_DECREF(finalResult);
449 throw Exception(msg);
455 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
457 OutputPyPort *p=(OutputPyPort *)*iter;
458 DEBTRACE( "port name: " << p->getName() );
459 DEBTRACE( "port kind: " << p->edGetType()->kind() );
460 DEBTRACE( "port pos : " << pos );
461 if(PyTuple_Check(finalResult))
462 ob=PyTuple_GetItem(finalResult,pos) ;
465 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
469 Py_DECREF(finalResult);
471 catch(ConversionException& ex)
473 Py_DECREF(finalResult);
474 _errorDetails=ex.what();
478 DEBTRACE( "++++++++++++++ ENDOF PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
481 void PythonNode::executeLocal()
483 DEBTRACE( "++++++++++++++ PyNode::executeLocal: " << getName() << " ++++++++++++++++++++" );
487 DEBTRACE( "---------------PyNode::inputs---------------" );
488 list<InputPort *>::iterator iter2;
489 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
491 InputPyPort *p=(InputPyPort *)*iter2;
492 DEBTRACE( "port name: " << p->getName() );
493 DEBTRACE( "port kind: " << p->edGetType()->kind() );
494 PyObject* ob=p->getPyObj();
495 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
497 PyObject_Print(ob,stderr,Py_PRINT_RAW);
500 int ier=PyDict_SetItemString(_context,p->getName().c_str(),ob);
501 DEBTRACE( "after PyDict_SetItemString:ob refcnt: " << ob->ob_refcnt );
504 DEBTRACE( "---------------End PyNode::inputs---------------" );
507 DEBTRACE( "----------------PyNode::calculation---------------" );
509 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
511 std::ostringstream stream;
512 stream << "/tmp/PythonNode_";
515 PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
519 PyObject* new_stderr = newPyStdOut(_errorDetails);
520 PySys_SetObject((char*)"stderr", new_stderr);
522 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
523 Py_DECREF(new_stderr);
524 throw Exception("Error during execution");
526 PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context);
530 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
533 if(PyErr_Occurred ())
536 PyObject* new_stderr = newPyStdOut(_errorDetails);
537 PySys_SetObject((char*)"stderr", new_stderr);
538 ofstream errorfile(stream.str().c_str());
539 if (errorfile.is_open())
541 errorfile << _script;
545 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
546 Py_DECREF(new_stderr);
547 throw Exception("Error during execution");
550 DEBTRACE( "-----------------PyNode::outputs-----------------" );
551 list<OutputPort *>::iterator iter;
554 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
556 OutputPyPort *p=(OutputPyPort *)*iter;
557 DEBTRACE( "port name: " << p->getName() );
558 DEBTRACE( "port kind: " << p->edGetType()->kind() );
559 PyObject *ob=PyDict_GetItemString(_context,p->getName().c_str());
562 std::string msg="Error during execution: there is no variable ";
563 msg=msg+p->getName()+" in node context";
565 throw Exception(msg);
567 DEBTRACE( "PyNode::outputs::ob refcnt: " << ob->ob_refcnt );
569 PyObject_Print(ob,stderr,Py_PRINT_RAW);
575 catch(ConversionException& ex)
577 _errorDetails=ex.what();
581 DEBTRACE( "-----------------End PyNode::outputs-----------------" );
583 DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" );
586 std::string PythonNode::getContainerLog()
588 if(_mode=="local")return "";
593 Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(this);
594 CORBA::String_var logname = objContainer->logfilename();
597 std::string::size_type pos = msg.find(":");
598 msg=msg.substr(pos+1);
602 msg = "Container no longer reachable";
607 void PythonNode::shutdown(int level)
609 DEBTRACE("PythonNode::shutdown " << level);
610 if(_mode=="local")return;
613 if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
614 _pynode=Engines::PyScriptNode::_nil();
615 _container->shutdown(level);
619 Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
621 return new PythonNode(*this,father);
624 void PythonNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer)
626 if(!CORBA::is_nil(_pynode))
627 _pynode->UnRegister();
628 _pynode=objContainer->createPyScriptNode(getName().c_str(),getScript().c_str());
631 Engines::PyNodeBase_var PythonNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const
633 Engines::PyScriptNode_var ret(objContainer->getDefaultPyScriptNode());
634 if(!CORBA::is_nil(ret))
638 return Engines::PyNodeBase::_narrow(ret);
641 void PythonNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp)
643 if(!CORBA::is_nil(_pynode))
645 Engines::PyScriptNode_var tmpp(Engines::PyScriptNode::_narrow(remoteInterp));
646 if(_pynode->_is_equivalent(tmpp))
649 if(!CORBA::is_nil(_pynode))
650 _pynode->UnRegister();
651 _pynode=Engines::PyScriptNode::_narrow(remoteInterp);
654 Engines::PyNodeBase_var PythonNode::getRemoteInterpreterHandle()
656 return Engines::PyNodeBase::_narrow(_pynode);
659 //! Create a new node of same type with a given name
660 PythonNode* PythonNode::cloneNode(const std::string& name)
662 PythonNode* n=new PythonNode(name);
663 n->setScript(_script);
664 list<InputPort *>::iterator iter;
665 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
667 InputPyPort *p=(InputPyPort *)*iter;
668 DEBTRACE( "port name: " << p->getName() );
669 DEBTRACE( "port kind: " << p->edGetType()->kind() );
670 n->edAddInputPort(p->getName(),p->edGetType());
672 list<OutputPort *>::iterator iter2;
673 for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
675 OutputPyPort *p=(OutputPyPort *)*iter2;
676 DEBTRACE( "port name: " << p->getName() );
677 DEBTRACE( "port kind: " << p->edGetType()->kind() );
678 n->edAddOutputPort(p->getName(),p->edGetType());
683 PyFuncNode::PyFuncNode(const PyFuncNode& other, ComposedNode *father):InlineFuncNode(other,father),_pyfunc(0)
685 _implementation = PythonNode::IMPL_NAME;
688 _context=PyDict_New();
689 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
690 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
693 msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
694 _errorDetails=msg.str();
695 throw Exception(msg.str());
700 PyFuncNode::PyFuncNode(const std::string& name): InlineFuncNode(name),_pyfunc(0)
703 _implementation = PythonNode::IMPL_NAME;
704 DEBTRACE( "PyFuncNode::PyFuncNode " << name );
707 _context=PyDict_New();
708 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
709 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
712 msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
713 _errorDetails=msg.str();
714 throw Exception(msg.str());
719 PyFuncNode::~PyFuncNode()
721 if(!CORBA::is_nil(_pynode))
723 _pynode->UnRegister();
727 void PyFuncNode::checkBasicConsistency() const throw(YACS::Exception)
729 DEBTRACE("checkBasicConsistency");
730 InlineFuncNode::checkBasicConsistency();
734 res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
737 std::string error="";
738 PyObject* new_stderr = newPyStdOut(error);
739 PySys_SetObject((char*)"stderr", new_stderr);
741 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
742 Py_DECREF(new_stderr);
743 throw Exception(error);
750 void PyFuncNode::load()
752 DEBTRACE( "---------------PyfuncNode::load function---------------" );
759 void PyFuncNode::loadRemote()
761 commonRemoteLoad(this);
764 void PyFuncNode::loadLocal()
766 DEBTRACE( "---------------PyFuncNode::load function " << getName() << " ---------------" );
770 list<OutputPort *>::iterator iter;
771 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
773 OutputPyPort *p=(OutputPyPort *)*iter;
774 DEBTRACE( "port name: " << p->getName() );
775 DEBTRACE( "port kind: " << p->edGetType()->kind() );
781 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
783 std::ostringstream stream;
784 stream << "/tmp/PythonNode_";
787 PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
791 PyObject* new_stderr = newPyStdOut(_errorDetails);
792 PySys_SetObject((char*)"stderr", new_stderr);
794 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
795 Py_DECREF(new_stderr);
796 throw Exception("Error during execution");
798 PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context);
802 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
803 if(PyErr_Occurred ())
806 PyObject* new_stderr = newPyStdOut(_errorDetails);
807 PySys_SetObject((char*)"stderr", new_stderr);
808 ofstream errorfile(stream.str().c_str());
809 if (errorfile.is_open())
811 errorfile << _script;
815 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
816 Py_DECREF(new_stderr);
817 throw Exception("Error during execution");
820 _pyfunc=PyDict_GetItemString(_context,_fname.c_str());
821 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
825 PyObject* new_stderr = newPyStdOut(_errorDetails);
826 PySys_SetObject((char*)"stderr", new_stderr);
828 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
829 Py_DECREF(new_stderr);
830 throw Exception("Error during execution");
832 DEBTRACE( "---------------End PyFuncNode::load function---------------" );
836 void PyFuncNode::execute()
844 void PyFuncNode::executeRemote()
846 DEBTRACE( "++++++++++++++ PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
848 throw Exception("DistributedPythonNode badly loaded");
850 if(dynamic_cast<HomogeneousPoolContainer *>(getContainer()))
853 commonRemoteLoadPart2(this,dummy);
854 _pynode->executeAnotherPieceOfCode(getScript().c_str());
857 Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);;
861 //===========================================================================
862 // Get inputs in input ports, build a Python tuple and pickle it
863 //===========================================================================
864 PyObject *args(PyTuple_New(getNumberOfInputPorts()));
866 for(std::list<InputPort *>::iterator iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++,pos++)
868 InputPyPort *p=(InputPyPort *)*iter2;
871 PyTuple_SetItem(args,pos,ob);
874 PyObject_Print(args,stderr,Py_PRINT_RAW);
877 PyObject *serializationInput=PyObject_CallObject(_pyfuncSer,args);
879 //The pickled string may contain NULL characters so use PyString_AsStringAndSize
880 char *serializationInputC(0);
882 if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len))
883 throw Exception("DistributedPythonNode problem in python pickle");
885 serializationInputCorba->length(len);
886 for(int i=0; i < len ; i++)
887 serializationInputCorba[i]=serializationInputC[i];
888 Py_DECREF(serializationInput);
891 //===========================================================================
892 // Execute in remote Python node
893 //===========================================================================
894 DEBTRACE( "-----------------starting remote python invocation-----------------" );
895 Engines::pickledArgs_var resultCorba;
898 resultCorba=_pynode->execute(getFname().c_str(),serializationInputCorba);
900 catch( const SALOME::SALOME_Exception& ex )
902 std::string msg="Exception on remote python invocation";
904 msg += ex.details.text.in();
906 throw Exception(msg);
908 DEBTRACE( "-----------------end of remote python invocation-----------------" );
909 //===========================================================================
910 // Get results, unpickle and put them in output ports
911 //===========================================================================
912 char *resultCorbaC=new char[resultCorba->length()+1];
913 resultCorbaC[resultCorba->length()]='\0';
914 for(int i=0;i<resultCorba->length();i++)
915 resultCorbaC[i]=resultCorba[i];
920 PyObject *resultPython(PyString_FromStringAndSize(resultCorbaC,resultCorba->length()));
921 delete [] resultCorbaC;
922 PyObject *args(PyTuple_New(1)),*ob(0);
923 PyTuple_SetItem(args,0,resultPython);
924 PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
927 DEBTRACE( "-----------------PythonNode::outputs-----------------" );
929 if(finalResult == Py_None)
931 else if(PyTuple_Check(finalResult))
932 nres=PyTuple_Size(finalResult);
934 if(getNumberOfOutputPorts() != nres)
936 std::string msg="Number of output arguments : Mismatch between definition and execution";
937 Py_DECREF(finalResult);
939 throw Exception(msg);
945 for(std::list<OutputPort *>::iterator iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++, pos++)
947 OutputPyPort *p=(OutputPyPort *)*iter;
948 DEBTRACE( "port name: " << p->getName() );
949 DEBTRACE( "port kind: " << p->edGetType()->kind() );
950 DEBTRACE( "port pos : " << pos );
951 if(PyTuple_Check(finalResult))
952 ob=PyTuple_GetItem(finalResult,pos) ;
955 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
958 Py_DECREF(finalResult);
960 catch(ConversionException& ex)
962 Py_DECREF(finalResult);
963 _errorDetails=ex.what();
968 DEBTRACE( "++++++++++++++ ENDOF PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
971 void PyFuncNode::executeLocal()
973 DEBTRACE( "++++++++++++++ PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
977 if(!_pyfunc)throw Exception("PyFuncNode badly loaded");
980 DEBTRACE( "---------------PyFuncNode::inputs---------------" );
981 PyObject* args = PyTuple_New(getNumberOfInputPorts()) ;
982 list<InputPort *>::iterator iter2;
983 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
985 InputPyPort *p=(InputPyPort *)*iter2;
986 DEBTRACE( "port name: " << p->getName() );
987 DEBTRACE( "port kind: " << p->edGetType()->kind() );
990 PyObject_Print(ob,stderr,Py_PRINT_RAW);
993 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
995 PyTuple_SetItem(args,pos,ob);
996 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
999 DEBTRACE( "---------------End PyFuncNode::inputs---------------" );
1001 DEBTRACE( "----------------PyFuncNode::calculation---------------" );
1003 PyObject_Print(_pyfunc,stderr,Py_PRINT_RAW);
1005 PyObject_Print(args,stderr,Py_PRINT_RAW);
1008 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
1009 PyObject* result = PyObject_CallObject( _pyfunc , args ) ;
1010 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
1017 PyObject* new_stderr = newPyStdOut(_errorDetails);
1018 PySys_SetObject((char*)"stderr", new_stderr);
1019 std::ostringstream stream;
1020 stream << "/tmp/PythonNode_";
1022 ofstream errorfile(stream.str().c_str());
1023 if (errorfile.is_open())
1025 errorfile << _script;
1029 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
1030 Py_DECREF(new_stderr);
1031 throw Exception("Error during execution");
1033 DEBTRACE( "----------------End PyFuncNode::calculation---------------" );
1035 DEBTRACE( "-----------------PyFuncNode::outputs-----------------" );
1037 if(result == Py_None)
1039 else if(PyTuple_Check(result))
1040 nres=PyTuple_Size(result);
1042 if(getNumberOfOutputPorts() != nres)
1044 std::string msg="Number of output arguments : Mismatch between definition and execution";
1047 throw Exception(msg);
1052 PyObject_Print(result,stderr,Py_PRINT_RAW);
1055 list<OutputPort *>::iterator iter;
1058 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
1060 OutputPyPort *p=(OutputPyPort *)*iter;
1061 DEBTRACE( "port name: " << p->getName() );
1062 DEBTRACE( "port kind: " << p->edGetType()->kind() );
1063 DEBTRACE( "port pos : " << pos );
1064 if(PyTuple_Check(result))ob=PyTuple_GetItem(result,pos) ;
1066 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1068 PyObject_Print(ob,stderr,Py_PRINT_RAW);
1075 catch(ConversionException& ex)
1078 _errorDetails=ex.what();
1081 DEBTRACE( "-----------------End PyFuncNode::outputs-----------------" );
1084 DEBTRACE( "++++++++++++++ End PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
1087 Node *PyFuncNode::simpleClone(ComposedNode *father, bool editionOnly) const
1089 return new PyFuncNode(*this,father);
1092 void PyFuncNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer)
1094 if(!CORBA::is_nil(_pynode))
1095 _pynode->UnRegister();
1096 _pynode=objContainer->createPyNode(getName().c_str(),getScript().c_str());
1099 Engines::PyNodeBase_var PyFuncNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const
1101 Engines::PyNode_var ret(objContainer->getDefaultPyNode());
1102 if(!CORBA::is_nil(ret))
1106 return Engines::PyNodeBase::_narrow(ret);
1109 void PyFuncNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp)
1111 if(!CORBA::is_nil(_pynode))
1113 Engines::PyNode_var tmpp(Engines::PyNode::_narrow(remoteInterp));
1114 if(_pynode->_is_equivalent(tmpp))
1117 if(!CORBA::is_nil(_pynode))
1118 _pynode->UnRegister();
1119 _pynode=Engines::PyNode::_narrow(remoteInterp);
1122 Engines::PyNodeBase_var PyFuncNode::getRemoteInterpreterHandle()
1124 return Engines::PyNodeBase::_narrow(_pynode);
1127 //! Create a new node of same type with a given name
1128 PyFuncNode* PyFuncNode::cloneNode(const std::string& name)
1130 PyFuncNode* n=new PyFuncNode(name);
1131 n->setScript(_script);
1132 n->setFname(_fname);
1133 list<InputPort *>::iterator iter;
1134 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
1136 InputPyPort *p=(InputPyPort *)*iter;
1137 n->edAddInputPort(p->getName(),p->edGetType());
1139 list<OutputPort *>::iterator iter2;
1140 for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
1142 OutputPyPort *p=(OutputPyPort *)*iter2;
1143 n->edAddOutputPort(p->getName(),p->edGetType());
1148 std::string PyFuncNode::getContainerLog()
1150 if(_mode=="local")return "";
1155 Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(this);
1156 CORBA::String_var logname = objContainer->logfilename();
1159 std::string::size_type pos = msg.find(":");
1160 msg=msg.substr(pos+1);
1164 msg = "Container no longer reachable";
1169 void PyFuncNode::shutdown(int level)
1171 DEBTRACE("PyFuncNode::shutdown " << level);
1172 if(_mode=="local")return;
1175 if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
1176 _pynode=Engines::PyNode::_nil();
1177 _container->shutdown(level);