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::commonRemoteLoad(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);
111 Engines::Container_var objContainer=Engines::Container::_nil();
113 throw Exception("No container specified !");
114 SalomeContainer *containerCast0(dynamic_cast<SalomeContainer *>(container));
115 SalomeHPContainer *containerCast1(dynamic_cast<SalomeHPContainer *>(container));
117 objContainer=containerCast0->getContainerPtr(reqNode);
118 else if(containerCast1)
120 YACS::BASES::AutoCppPtr<SalomeContainerTmpForHP> tmpCont(SalomeContainerTmpForHP::BuildFrom(containerCast1,reqNode));
121 objContainer=tmpCont->getContainerPtr(reqNode);
124 throw Exception("Unrecognized type of container ! Salome one is expected for PythonNode/PyFuncNode !");
125 if(CORBA::is_nil(objContainer))
126 throw Exception("Container corba pointer is NULL for PythonNode !");
127 bool isInitializeRequested(false);
132 createRemoteAdaptedPyInterpretor(objContainer);
136 Engines::PyNodeBase_var dftPyScript(retrieveDftRemotePyInterpretorIfAny(objContainer));
137 if(CORBA::is_nil(dftPyScript))
139 isInitializeRequested=true;
140 createRemoteAdaptedPyInterpretor(objContainer);
143 assignRemotePyInterpretor(dftPyScript);
146 catch( const SALOME::SALOME_Exception& ex )
148 std::string msg="Exception on remote python node creation ";
150 msg += ex.details.text.in();
151 reqNode->setErrorDetails(msg);
152 throw Exception(msg);
154 Engines::PyNodeBase_var pynode(getRemoteInterpreterHandle());
155 if(CORBA::is_nil(pynode))
156 throw Exception("In PythonNode the ref in NULL ! ");
160 const char *picklizeScript(getSerializationScript());
161 PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context);
164 std::string errorDetails;
165 PyObject* new_stderr = newPyStdOut(errorDetails);
166 reqNode->setErrorDetails(errorDetails);
167 PySys_SetObject((char*)"stderr", new_stderr);
169 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
170 Py_DECREF(new_stderr);
171 throw Exception("Error during load");
174 _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009");
175 _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009");
176 if(_pyfuncSer == NULL)
178 std::string errorDetails;
179 PyObject *new_stderr(newPyStdOut(errorDetails));
180 reqNode->setErrorDetails(errorDetails);
181 PySys_SetObject((char*)"stderr", new_stderr);
183 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
184 Py_DECREF(new_stderr);
185 throw Exception("Error during load");
187 if(_pyfuncUnser == NULL)
189 std::string errorDetails;
190 PyObject *new_stderr(newPyStdOut(errorDetails));
191 reqNode->setErrorDetails(errorDetails);
192 PySys_SetObject((char*)"stderr", new_stderr);
194 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
195 Py_DECREF(new_stderr);
196 throw Exception("Error during load");
198 if(isInitializeRequested)
199 {//This one is called only once at initialization in the container if an init-script is specified.
202 std::string zeInitScriptKey(container->getProperty(HomogeneousPoolContainer::INITIALIZE_SCRIPT_KEY));
203 if(!zeInitScriptKey.empty())
204 pynode->executeAnotherPieceOfCode(zeInitScriptKey.c_str());
206 catch( const SALOME::SALOME_Exception& ex )
208 std::string msg="Exception on PythonNode::loadRemote python invocation of initializisation py script !";
210 msg += ex.details.text.in();
211 reqNode->setErrorDetails(msg);
212 throw Exception(msg);
215 DEBTRACE( "---------------End PyNode::loadRemote function---------------" );
219 PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father)
221 _implementation=IMPL_NAME;
224 _context=PyDict_New();
225 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
228 msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
229 _errorDetails=msg.str();
230 throw Exception(msg.str());
235 PythonNode::PythonNode(const std::string& name):InlineNode(name)
237 _implementation=IMPL_NAME;
240 _context=PyDict_New();
241 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
244 msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
245 _errorDetails=msg.str();
246 throw Exception(msg.str());
251 PythonNode::~PythonNode()
253 if(!CORBA::is_nil(_pynode))
255 _pynode->UnRegister();
259 void PythonNode::checkBasicConsistency() const throw(YACS::Exception)
261 DEBTRACE("checkBasicConsistency");
262 InlineNode::checkBasicConsistency();
266 res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
269 std::string error="";
270 PyObject* new_stderr = newPyStdOut(error);
271 PySys_SetObject((char*)"stderr", new_stderr);
273 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
274 Py_DECREF(new_stderr);
275 throw Exception(error);
282 void PythonNode::load()
284 DEBTRACE( "---------------PyNode::load function---------------" );
291 void PythonNode::loadLocal()
293 DEBTRACE( "---------------PyNode::loadLocal function---------------" );
297 void PythonNode::loadRemote()
299 commonRemoteLoad(this);
302 void PythonNode::execute()
310 void PythonNode::executeRemote()
312 DEBTRACE( "++++++++++++++ PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
314 throw Exception("DistributedPythonNode badly loaded");
315 Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);
318 PyObject *args(0),*ob(0);
319 //===========================================================================
320 // Get inputs in input ports, build a Python dict and pickle it
321 //===========================================================================
323 std::list<InputPort *>::iterator iter2;
325 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); ++iter2)
327 InputPyPort *p=(InputPyPort *)*iter2;
329 PyDict_SetItemString(args,p->getName().c_str(),ob);
333 PyObject_Print(args,stderr,Py_PRINT_RAW);
336 PyObject *serializationInput(PyObject_CallFunctionObjArgs(_pyfuncSer,args,NULL));
338 //The pickled string may contain NULL characters so use PyString_AsStringAndSize
339 char *serializationInputC(0);
341 if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len))
342 throw Exception("DistributedPythonNode problem in python pickle");
343 serializationInputCorba->length(len);
344 for(int i=0; i < len ; i++)
345 serializationInputCorba[i]=serializationInputC[i];
346 Py_DECREF(serializationInput);
349 //get the list of output argument names
350 std::list<OutputPort *>::iterator iter;
351 Engines::listofstring myseq;
352 myseq.length(getNumberOfOutputPorts());
354 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
356 OutputPyPort *p=(OutputPyPort *)*iter;
357 myseq[pos]=p->getName().c_str();
358 DEBTRACE( "port name: " << p->getName() );
359 DEBTRACE( "port kind: " << p->edGetType()->kind() );
360 DEBTRACE( "port pos : " << pos );
363 //===========================================================================
364 // Execute in remote Python node
365 //===========================================================================
366 DEBTRACE( "-----------------starting remote python invocation-----------------" );
367 Engines::pickledArgs_var resultCorba;
370 //pass outargsname and dict serialized
371 resultCorba=_pynode->execute(myseq,serializationInputCorba);
373 catch( const SALOME::SALOME_Exception& ex )
375 std::string msg="Exception on remote python invocation";
377 msg += ex.details.text.in();
379 throw Exception(msg);
381 DEBTRACE( "-----------------end of remote python invocation-----------------" );
382 //===========================================================================
383 // Get results, unpickle and put them in output ports
384 //===========================================================================
385 char *resultCorbaC=new char[resultCorba->length()+1];
386 resultCorbaC[resultCorba->length()]='\0';
387 for(int i=0;i<resultCorba->length();i++)
388 resultCorbaC[i]=resultCorba[i];
392 PyObject *args(0),*ob(0);
393 PyObject* resultPython=PyString_FromStringAndSize(resultCorbaC,resultCorba->length());
394 delete [] resultCorbaC;
395 args = PyTuple_New(1);
396 PyTuple_SetItem(args,0,resultPython);
397 PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
400 if (finalResult == NULL)
402 std::stringstream msg;
403 msg << "Conversion with pickle of output ports failed !";
404 msg << " : " << __FILE__ << ":" << __LINE__;
405 _errorDetails=msg.str();
406 throw YACS::ENGINE::ConversionException(msg.str());
409 DEBTRACE( "-----------------PythonNode::outputs-----------------" );
411 if(finalResult == Py_None)
413 else if(PyTuple_Check(finalResult))
414 nres=PyTuple_Size(finalResult);
416 if(getNumberOfOutputPorts() != nres)
418 std::string msg="Number of output arguments : Mismatch between definition and execution";
419 Py_DECREF(finalResult);
421 throw Exception(msg);
427 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
429 OutputPyPort *p=(OutputPyPort *)*iter;
430 DEBTRACE( "port name: " << p->getName() );
431 DEBTRACE( "port kind: " << p->edGetType()->kind() );
432 DEBTRACE( "port pos : " << pos );
433 if(PyTuple_Check(finalResult))
434 ob=PyTuple_GetItem(finalResult,pos) ;
437 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
441 Py_DECREF(finalResult);
443 catch(ConversionException& ex)
445 Py_DECREF(finalResult);
446 _errorDetails=ex.what();
450 DEBTRACE( "++++++++++++++ ENDOF PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
453 void PythonNode::executeLocal()
455 DEBTRACE( "++++++++++++++ PyNode::executeLocal: " << getName() << " ++++++++++++++++++++" );
459 DEBTRACE( "---------------PyNode::inputs---------------" );
460 list<InputPort *>::iterator iter2;
461 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
463 InputPyPort *p=(InputPyPort *)*iter2;
464 DEBTRACE( "port name: " << p->getName() );
465 DEBTRACE( "port kind: " << p->edGetType()->kind() );
466 PyObject* ob=p->getPyObj();
467 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
469 PyObject_Print(ob,stderr,Py_PRINT_RAW);
472 int ier=PyDict_SetItemString(_context,p->getName().c_str(),ob);
473 DEBTRACE( "after PyDict_SetItemString:ob refcnt: " << ob->ob_refcnt );
476 DEBTRACE( "---------------End PyNode::inputs---------------" );
479 DEBTRACE( "----------------PyNode::calculation---------------" );
481 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
483 std::ostringstream stream;
484 stream << "/tmp/PythonNode_";
487 PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
491 PyObject* new_stderr = newPyStdOut(_errorDetails);
492 PySys_SetObject((char*)"stderr", new_stderr);
494 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
495 Py_DECREF(new_stderr);
496 throw Exception("Error during execution");
498 PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context);
502 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
505 if(PyErr_Occurred ())
508 PyObject* new_stderr = newPyStdOut(_errorDetails);
509 PySys_SetObject((char*)"stderr", new_stderr);
510 ofstream errorfile(stream.str().c_str());
511 if (errorfile.is_open())
513 errorfile << _script;
517 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
518 Py_DECREF(new_stderr);
519 throw Exception("Error during execution");
522 DEBTRACE( "-----------------PyNode::outputs-----------------" );
523 list<OutputPort *>::iterator iter;
526 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
528 OutputPyPort *p=(OutputPyPort *)*iter;
529 DEBTRACE( "port name: " << p->getName() );
530 DEBTRACE( "port kind: " << p->edGetType()->kind() );
531 PyObject *ob=PyDict_GetItemString(_context,p->getName().c_str());
534 std::string msg="Error during execution: there is no variable ";
535 msg=msg+p->getName()+" in node context";
537 throw Exception(msg);
539 DEBTRACE( "PyNode::outputs::ob refcnt: " << ob->ob_refcnt );
541 PyObject_Print(ob,stderr,Py_PRINT_RAW);
547 catch(ConversionException& ex)
549 _errorDetails=ex.what();
553 DEBTRACE( "-----------------End PyNode::outputs-----------------" );
555 DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" );
558 std::string PythonNode::getContainerLog()
560 if(_mode=="local")return "";
565 Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(this);
566 CORBA::String_var logname = objContainer->logfilename();
569 std::string::size_type pos = msg.find(":");
570 msg=msg.substr(pos+1);
574 msg = "Container no longer reachable";
579 void PythonNode::shutdown(int level)
581 DEBTRACE("PythonNode::shutdown " << level);
582 if(_mode=="local")return;
585 if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
586 _pynode=Engines::PyScriptNode::_nil();
587 _container->shutdown(level);
591 Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
593 return new PythonNode(*this,father);
596 void PythonNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer)
598 if(!CORBA::is_nil(_pynode))
599 _pynode->UnRegister();
600 _pynode=objContainer->createPyScriptNode(getName().c_str(),getScript().c_str());
603 Engines::PyNodeBase_var PythonNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const
605 Engines::PyScriptNode_var ret(objContainer->getDefaultPyScriptNode());
606 if(!CORBA::is_nil(ret))
610 return Engines::PyNodeBase::_narrow(ret);
613 void PythonNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp)
615 if(!CORBA::is_nil(_pynode))
617 Engines::PyScriptNode_var tmpp(Engines::PyScriptNode::_narrow(remoteInterp));
618 if(_pynode->_is_equivalent(tmpp))
621 if(!CORBA::is_nil(_pynode))
622 _pynode->UnRegister();
623 _pynode=Engines::PyScriptNode::_narrow(remoteInterp);
626 Engines::PyNodeBase_var PythonNode::getRemoteInterpreterHandle()
628 return Engines::PyNodeBase::_narrow(_pynode);
631 //! Create a new node of same type with a given name
632 PythonNode* PythonNode::cloneNode(const std::string& name)
634 PythonNode* n=new PythonNode(name);
635 n->setScript(_script);
636 list<InputPort *>::iterator iter;
637 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
639 InputPyPort *p=(InputPyPort *)*iter;
640 DEBTRACE( "port name: " << p->getName() );
641 DEBTRACE( "port kind: " << p->edGetType()->kind() );
642 n->edAddInputPort(p->getName(),p->edGetType());
644 list<OutputPort *>::iterator iter2;
645 for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
647 OutputPyPort *p=(OutputPyPort *)*iter2;
648 DEBTRACE( "port name: " << p->getName() );
649 DEBTRACE( "port kind: " << p->edGetType()->kind() );
650 n->edAddOutputPort(p->getName(),p->edGetType());
655 PyFuncNode::PyFuncNode(const PyFuncNode& other, ComposedNode *father):InlineFuncNode(other,father),_pyfunc(0)
657 _implementation = PythonNode::IMPL_NAME;
660 _context=PyDict_New();
661 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
662 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
665 msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
666 _errorDetails=msg.str();
667 throw Exception(msg.str());
672 PyFuncNode::PyFuncNode(const std::string& name): InlineFuncNode(name),_pyfunc(0)
675 _implementation = PythonNode::IMPL_NAME;
676 DEBTRACE( "PyFuncNode::PyFuncNode " << name );
679 _context=PyDict_New();
680 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
681 if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
684 msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
685 _errorDetails=msg.str();
686 throw Exception(msg.str());
691 PyFuncNode::~PyFuncNode()
693 if(!CORBA::is_nil(_pynode))
695 _pynode->UnRegister();
699 void PyFuncNode::checkBasicConsistency() const throw(YACS::Exception)
701 DEBTRACE("checkBasicConsistency");
702 InlineFuncNode::checkBasicConsistency();
706 res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
709 std::string error="";
710 PyObject* new_stderr = newPyStdOut(error);
711 PySys_SetObject((char*)"stderr", new_stderr);
713 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
714 Py_DECREF(new_stderr);
715 throw Exception(error);
722 void PyFuncNode::load()
724 DEBTRACE( "---------------PyfuncNode::load function---------------" );
731 void PyFuncNode::loadRemote()
733 commonRemoteLoad(this);
736 void PyFuncNode::loadLocal()
738 DEBTRACE( "---------------PyFuncNode::load function " << getName() << " ---------------" );
742 list<OutputPort *>::iterator iter;
743 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
745 OutputPyPort *p=(OutputPyPort *)*iter;
746 DEBTRACE( "port name: " << p->getName() );
747 DEBTRACE( "port kind: " << p->edGetType()->kind() );
753 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
755 std::ostringstream stream;
756 stream << "/tmp/PythonNode_";
759 PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
763 PyObject* new_stderr = newPyStdOut(_errorDetails);
764 PySys_SetObject((char*)"stderr", new_stderr);
766 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
767 Py_DECREF(new_stderr);
768 throw Exception("Error during execution");
770 PyObject *res = PyEval_EvalCode((PyCodeObject *)code, _context, _context);
774 DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
775 if(PyErr_Occurred ())
778 PyObject* new_stderr = newPyStdOut(_errorDetails);
779 PySys_SetObject((char*)"stderr", new_stderr);
780 ofstream errorfile(stream.str().c_str());
781 if (errorfile.is_open())
783 errorfile << _script;
787 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
788 Py_DECREF(new_stderr);
789 throw Exception("Error during execution");
792 _pyfunc=PyDict_GetItemString(_context,_fname.c_str());
793 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
797 PyObject* new_stderr = newPyStdOut(_errorDetails);
798 PySys_SetObject((char*)"stderr", new_stderr);
800 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
801 Py_DECREF(new_stderr);
802 throw Exception("Error during execution");
804 DEBTRACE( "---------------End PyFuncNode::load function---------------" );
808 void PyFuncNode::execute()
816 void PyFuncNode::executeRemote()
818 DEBTRACE( "++++++++++++++ PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
820 throw Exception("DistributedPythonNode badly loaded");
821 Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);;
825 //===========================================================================
826 // Get inputs in input ports, build a Python tuple and pickle it
827 //===========================================================================
828 PyObject *args(PyTuple_New(getNumberOfInputPorts()));
830 for(std::list<InputPort *>::iterator iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++,pos++)
832 InputPyPort *p=(InputPyPort *)*iter2;
835 PyTuple_SetItem(args,pos,ob);
838 PyObject_Print(args,stderr,Py_PRINT_RAW);
841 PyObject *serializationInput=PyObject_CallObject(_pyfuncSer,args);
843 //The pickled string may contain NULL characters so use PyString_AsStringAndSize
844 char *serializationInputC(0);
846 if (PyString_AsStringAndSize(serializationInput, &serializationInputC, &len))
847 throw Exception("DistributedPythonNode problem in python pickle");
849 serializationInputCorba->length(len);
850 for(int i=0; i < len ; i++)
851 serializationInputCorba[i]=serializationInputC[i];
852 Py_DECREF(serializationInput);
855 //===========================================================================
856 // Execute in remote Python node
857 //===========================================================================
858 DEBTRACE( "-----------------starting remote python invocation-----------------" );
859 Engines::pickledArgs_var resultCorba;
862 resultCorba=_pynode->execute(getFname().c_str(),serializationInputCorba);
864 catch( const SALOME::SALOME_Exception& ex )
866 std::string msg="Exception on remote python invocation";
868 msg += ex.details.text.in();
870 throw Exception(msg);
872 DEBTRACE( "-----------------end of remote python invocation-----------------" );
873 //===========================================================================
874 // Get results, unpickle and put them in output ports
875 //===========================================================================
876 char *resultCorbaC=new char[resultCorba->length()+1];
877 resultCorbaC[resultCorba->length()]='\0';
878 for(int i=0;i<resultCorba->length();i++)
879 resultCorbaC[i]=resultCorba[i];
884 PyObject *resultPython(PyString_FromStringAndSize(resultCorbaC,resultCorba->length()));
885 delete [] resultCorbaC;
886 PyObject *args(PyTuple_New(1)),*ob(0);
887 PyTuple_SetItem(args,0,resultPython);
888 PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
891 DEBTRACE( "-----------------PythonNode::outputs-----------------" );
893 if(finalResult == Py_None)
895 else if(PyTuple_Check(finalResult))
896 nres=PyTuple_Size(finalResult);
898 if(getNumberOfOutputPorts() != nres)
900 std::string msg="Number of output arguments : Mismatch between definition and execution";
901 Py_DECREF(finalResult);
903 throw Exception(msg);
909 for(std::list<OutputPort *>::iterator iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++, pos++)
911 OutputPyPort *p=(OutputPyPort *)*iter;
912 DEBTRACE( "port name: " << p->getName() );
913 DEBTRACE( "port kind: " << p->edGetType()->kind() );
914 DEBTRACE( "port pos : " << pos );
915 if(PyTuple_Check(finalResult))
916 ob=PyTuple_GetItem(finalResult,pos) ;
919 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
922 Py_DECREF(finalResult);
924 catch(ConversionException& ex)
926 Py_DECREF(finalResult);
927 _errorDetails=ex.what();
932 DEBTRACE( "++++++++++++++ ENDOF PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
935 void PyFuncNode::executeLocal()
937 DEBTRACE( "++++++++++++++ PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
941 if(!_pyfunc)throw Exception("PyFuncNode badly loaded");
944 DEBTRACE( "---------------PyFuncNode::inputs---------------" );
945 PyObject* args = PyTuple_New(getNumberOfInputPorts()) ;
946 list<InputPort *>::iterator iter2;
947 for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
949 InputPyPort *p=(InputPyPort *)*iter2;
950 DEBTRACE( "port name: " << p->getName() );
951 DEBTRACE( "port kind: " << p->edGetType()->kind() );
954 PyObject_Print(ob,stderr,Py_PRINT_RAW);
957 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
959 PyTuple_SetItem(args,pos,ob);
960 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
963 DEBTRACE( "---------------End PyFuncNode::inputs---------------" );
965 DEBTRACE( "----------------PyFuncNode::calculation---------------" );
967 PyObject_Print(_pyfunc,stderr,Py_PRINT_RAW);
969 PyObject_Print(args,stderr,Py_PRINT_RAW);
972 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
973 PyObject* result = PyObject_CallObject( _pyfunc , args ) ;
974 DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
981 PyObject* new_stderr = newPyStdOut(_errorDetails);
982 PySys_SetObject((char*)"stderr", new_stderr);
983 std::ostringstream stream;
984 stream << "/tmp/PythonNode_";
986 ofstream errorfile(stream.str().c_str());
987 if (errorfile.is_open())
989 errorfile << _script;
993 PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
994 Py_DECREF(new_stderr);
995 throw Exception("Error during execution");
997 DEBTRACE( "----------------End PyFuncNode::calculation---------------" );
999 DEBTRACE( "-----------------PyFuncNode::outputs-----------------" );
1001 if(result == Py_None)
1003 else if(PyTuple_Check(result))
1004 nres=PyTuple_Size(result);
1006 if(getNumberOfOutputPorts() != nres)
1008 std::string msg="Number of output arguments : Mismatch between definition and execution";
1011 throw Exception(msg);
1016 PyObject_Print(result,stderr,Py_PRINT_RAW);
1019 list<OutputPort *>::iterator iter;
1022 for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
1024 OutputPyPort *p=(OutputPyPort *)*iter;
1025 DEBTRACE( "port name: " << p->getName() );
1026 DEBTRACE( "port kind: " << p->edGetType()->kind() );
1027 DEBTRACE( "port pos : " << pos );
1028 if(PyTuple_Check(result))ob=PyTuple_GetItem(result,pos) ;
1030 DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1032 PyObject_Print(ob,stderr,Py_PRINT_RAW);
1039 catch(ConversionException& ex)
1042 _errorDetails=ex.what();
1045 DEBTRACE( "-----------------End PyFuncNode::outputs-----------------" );
1048 DEBTRACE( "++++++++++++++ End PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
1051 Node *PyFuncNode::simpleClone(ComposedNode *father, bool editionOnly) const
1053 return new PyFuncNode(*this,father);
1056 void PyFuncNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer)
1058 if(!CORBA::is_nil(_pynode))
1059 _pynode->UnRegister();
1060 _pynode=objContainer->createPyNode(getName().c_str(),getScript().c_str());
1063 Engines::PyNodeBase_var PyFuncNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const
1065 Engines::PyNode_var ret(objContainer->getDefaultPyNode());
1066 if(!CORBA::is_nil(ret))
1070 return Engines::PyNodeBase::_narrow(ret);
1073 void PyFuncNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp)
1075 if(!CORBA::is_nil(_pynode))
1077 Engines::PyNode_var tmpp(Engines::PyNode::_narrow(remoteInterp));
1078 if(_pynode->_is_equivalent(tmpp))
1081 if(!CORBA::is_nil(_pynode))
1082 _pynode->UnRegister();
1083 _pynode=Engines::PyNode::_narrow(remoteInterp);
1086 Engines::PyNodeBase_var PyFuncNode::getRemoteInterpreterHandle()
1088 return Engines::PyNodeBase::_narrow(_pynode);
1091 //! Create a new node of same type with a given name
1092 PyFuncNode* PyFuncNode::cloneNode(const std::string& name)
1094 PyFuncNode* n=new PyFuncNode(name);
1095 n->setScript(_script);
1096 n->setFname(_fname);
1097 list<InputPort *>::iterator iter;
1098 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
1100 InputPyPort *p=(InputPyPort *)*iter;
1101 n->edAddInputPort(p->getName(),p->edGetType());
1103 list<OutputPort *>::iterator iter2;
1104 for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
1106 OutputPyPort *p=(OutputPyPort *)*iter2;
1107 n->edAddOutputPort(p->getName(),p->edGetType());
1112 std::string PyFuncNode::getContainerLog()
1114 if(_mode=="local")return "";
1119 Engines::Container_var objContainer=((SalomeContainer*)_container)->getContainerPtr(this);
1120 CORBA::String_var logname = objContainer->logfilename();
1123 std::string::size_type pos = msg.find(":");
1124 msg=msg.substr(pos+1);
1128 msg = "Container no longer reachable";
1133 void PyFuncNode::shutdown(int level)
1135 DEBTRACE("PyFuncNode::shutdown " << level);
1136 if(_mode=="local")return;
1139 if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
1140 _pynode=Engines::PyNode::_nil();
1141 _container->shutdown(level);