The Gaudi Framework  master (ff829712)
Loading...
Searching...
No Matches
PythonScriptingSvc.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#include <Python.h>
12#include <cpython/initconfig.h>
13
14// Include Files
17#include <GaudiKernel/SmartIF.h>
18
19#include "PythonScriptingSvc.h"
20
21#include <fstream>
22#include <sstream>
23
24// Special for Unixes
25#if defined( __linux )
26# include <dlfcn.h>
27#endif
28
29// Instantiation of a static factory class used by clients to create
30// instances of this service
32
33//----------------------------------------------------------------------------------
35 //----------------------------------------------------------------------------------
36 : base_class( name, svc ) {
37 // Declare the startup script Property
38 declareProperty( "StartupScript", m_startupScript = "" );
39}
40
41//----------------------------------------------------------------------------------
43//----------------------------------------------------------------------------------
44
45//----------------------------------------------------------------------------------
47//----------------------------------------------------------------------------------
48{
49 // initialize the Service Base class
51 if ( sc.isFailure() ) return sc;
52
53 // Setup startup script. If none is explicitly specified, then
54 // use the ApplicationMgr JobOptionsPath property as long as
55 // the JobOptionsType property is set to "NONE".
56 if ( m_startupScript.empty() ) {
57 auto prpMgr = serviceLocator()->as<IProperty>();
58 if ( prpMgr ) {
60 tmp.assign( prpMgr->getProperty( "JobOptionsType" ) );
61 if ( tmp.value() == "NONE" ) {
62 tmp.assign( prpMgr->getProperty( "JobOptionsPath" ) );
63 m_startupScript = tmp;
64 }
65 }
66 }
67
68 wchar_t* progName[] = { const_cast<wchar_t*>( L"GaudiPython" ) };
69
70 PyStatus status;
71
72 PyConfig config;
73 PyConfig_InitPythonConfig( &config );
74
75 status = PyConfig_SetString( &config, &config.program_name, progName[0] );
76 // Set argv for Tkinter (needs program name)
77 status = PyConfig_SetArgv( &config, 1, progName );
78 status = Py_InitializeFromConfig( &config );
79 PyConfig_Clear( &config );
80
81 // Get the Python version
82 std::string fullversion = Py_GetVersion();
83 std::string version( fullversion, 0, fullversion.find_first_of( ' ' ) );
84 std::string vers( version, 0, version.find_first_of( '.', version.find_first_of( '.' ) + 1 ) );
85 info() << "Python version: [" << vers << "]" << endmsg;
86
87#if defined( __linux )
88 // This is hack to make global the python symbols
89 // which are needed by the other python modules
90 // (eg. readline, math, etc,) libraries.
91 std::string libname = "libpython" + vers + ".so";
92 dlopen( libname.c_str(), RTLD_GLOBAL | RTLD_LAZY );
93#endif
94
95 // Startup commands
96 PyRun_SimpleString( "from gaudimodule import *" );
97 PyRun_SimpleString( "g = AppMgr()" );
98 // backward compatibility with SIPython
99 PyRun_SimpleString( "theApp = g" );
100 PyRun_SimpleString( "def Service(n): return g.service(n)" );
101 PyRun_SimpleString( "def Algorithm(n): return g.algorithm(n)" );
102 PyRun_SimpleString( "def Property(n): return g.service(n)" );
103 // For command-line completion
104 PyRun_SimpleString( "import rlcompleter" );
105 PyRun_SimpleString( "rlcompleter.readline.parse_and_bind('tab: complete')" );
106 return StatusCode::SUCCESS;
107}
108
109//----------------------------------------------------------------------------------
111//----------------------------------------------------------------------------------
112{
113 // Finalize this specific service
115 if ( sc.isFailure() ) return sc;
116
117 // Shutdown the Python interpreter
118 Py_Finalize();
119 return StatusCode::SUCCESS;
120}
121
122//----------------------------------------------------------------------------------
124//----------------------------------------------------------------------------------
125{
126 if ( !m_startupScript.empty() ) {
127 std::ifstream file{ m_startupScript };
128 std::stringstream stream;
129 if ( file ) {
130 std::string buffer;
131 file.seekg( 0, std::ios::end );
132 buffer.reserve( file.tellg() );
133 file.seekg( 0, std::ios::beg );
134 buffer.assign( ( std::istreambuf_iterator<char>{ file } ), std::istreambuf_iterator<char>{} );
135 file.close();
136 PyRun_SimpleString( buffer.c_str() );
137 } else {
138 warning() << "Python startup file " << m_startupScript << " not found" << endmsg;
139 }
140 }
141 PyRun_InteractiveLoop( stdin, "\0" );
142 return StatusCode::SUCCESS;
143}
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define DECLARE_COMPONENT(type)
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
const ValueType & value() const
Definition Property.h:229
bool assign(const Details::PropertyBase &source) override
get the value from another property
Definition Property.h:361
The IProperty is the basic interface for all components which have properties that can be set or get.
Definition IProperty.h:32
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition ISvcLocator.h:42
SmartIF< IFace > as()
Definition ISvcLocator.h:64
This service handles scripting implemented using Python.
std::string m_startupScript
Startup script.
~PythonScriptingSvc() override
Destructor.
StatusCode initialize() override
Initialize the service. [IService::initialize()].
StatusCode finalize() override
Finalize the service. [IService::finalize()].
StatusCode run() override
Run the service by taking full control. [IRunable::run()].
PythonScriptingSvc(const std::string &name, ISvcLocator *svc)
Standard Constructor.
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator.
Definition Service.cpp:336
StatusCode finalize() override
Definition Service.cpp:223
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
Gaudi::Details::PropertyBase * declareProperty(const std::string &name, ToolHandle< T > &hndl, const std::string &doc="none")
Definition Service.h:91
StatusCode initialize() override
Definition Service.cpp:118
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
constexpr static const auto SUCCESS
Definition StatusCode.h:99
STL namespace.