Skip to content

Commit a7515ad

Browse files
carolinuxelpaso
authored andcommittedAug 4, 2015
Made python initialization less verbose
1 parent 745f91d commit a7515ad

File tree

2 files changed

+70
-156
lines changed

2 files changed

+70
-156
lines changed
 

‎src/python/qgspythonutilsimpl.cpp

Lines changed: 63 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,8 @@ QgsPythonUtilsImpl::~QgsPythonUtilsImpl()
4949
#endif
5050
}
5151

52-
void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
53-
{
54-
// initialize python
55-
Py_Initialize();
56-
57-
// initialize threading AND acquire GIL
58-
PyEval_InitThreads();
59-
60-
mPythonEnabled = true;
52+
bool QgsPythonUtilsImpl::checkSystemImports() {
6153

62-
mMainModule = PyImport_AddModule( "__main__" ); // borrowed reference
63-
mMainDict = PyModule_GetDict( mMainModule ); // borrowed reference
6454

6555
runString( "import sys" ); // import sys module (for display / exception hooks)
6656
runString( "import os" ); // import os module (for user paths)
@@ -116,8 +106,7 @@ void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
116106
if ( !runString( "import sip",
117107
QObject::tr( "Couldn't load SIP module." ) + "\n" + QObject::tr( "Python support will be disabled." ) ) )
118108
{
119-
exitPython();
120-
return;
109+
return false;
121110
}
122111

123112
// set PyQt4 api versions
@@ -128,36 +117,40 @@ void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
128117
if ( !runString( QString( "sip.setapi('%1', 2)" ).arg( clsName ),
129118
QObject::tr( "Couldn't set SIP API versions." ) + "\n" + QObject::tr( "Python support will be disabled." ) ) )
130119
{
131-
exitPython();
132-
return;
120+
return false;
133121
}
134122
}
135123

136124
// import Qt bindings
137125
if ( !runString( "from PyQt4 import QtCore, QtGui",
138126
QObject::tr( "Couldn't load PyQt4." ) + "\n" + QObject::tr( "Python support will be disabled." ) ) )
139127
{
140-
exitPython();
141-
return;
128+
return false;
142129
}
143130

144131
// import QGIS bindings
145132
QString error_msg = QObject::tr( "Couldn't load PyQGIS." ) + "\n" + QObject::tr( "Python support will be disabled." );
146133
if ( !runString( "from qgis.core import *", error_msg ) || !runString( "from qgis.gui import *", error_msg ) )
147134
{
148-
exitPython();
149-
return;
135+
return false;
150136
}
151137

138+
#ifdef HAVE_SERVER_PYTHON_PLUGINS
139+
// This is the main difference with initInterface() for desktop plugins
140+
// import QGIS Server bindings
141+
error_msg = QObject::tr( "Couldn't load PyQGIS Server." ) + "\n" + QObject::tr( "Python support will be disabled." );
142+
if ( !runString( "from qgis.server import *", error_msg ) )
143+
{
144+
return false;
145+
}
146+
#endif
152147
// import QGIS utils
153148
error_msg = QObject::tr( "Couldn't load QGIS utils." ) + "\n" + QObject::tr( "Python support will be disabled." );
154149
if ( !runString( "import qgis.utils", error_msg ) )
155150
{
156-
exitPython();
157-
return;
151+
return false;
158152
}
159153

160-
161154
// tell the utils script where to look for the plugins
162155
runString( "qgis.utils.plugin_paths = [" + pluginpaths.join( "," ) + "]" );
163156
runString( "qgis.utils.sys_plugin_path = \"" + pluginsPath() + "\"" );
@@ -167,167 +160,81 @@ void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
167160
runString( "if oldhome: os.environ['HOME']=oldhome\n" );
168161
#endif
169162

170-
// initialize 'iface' object
171-
runString( "qgis.utils.initInterface(" + QString::number(( unsigned long ) interface ) + ")" );
172-
173-
// import QGIS user
174-
error_msg = QObject::tr( "Couldn't load qgis.user." ) + "\n" + QObject::tr( "Python support will be disabled." );
175-
if ( !runString( "import qgis.user", error_msg ) )
176-
{
177-
// Should we really bail because of this?!
178-
exitPython();
179-
return;
180-
}
181-
182-
// release GIL!
183-
// Later on, we acquire GIL just before doing some Python calls and
184-
// release GIL again when the work with Python API is done.
185-
// (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
186-
// around any calls to Python API, otherwise we may segfault!)
187-
_mainState = PyEval_SaveThread();
163+
return true;
188164
}
189-
190-
191-
#ifdef HAVE_SERVER_PYTHON_PLUGINS
192-
void QgsPythonUtilsImpl::initServerPython( QgsServerInterface* interface )
193-
{
165+
void QgsPythonUtilsImpl::init() {
194166
// initialize python
195167
Py_Initialize();
196-
197168
// initialize threading AND acquire GIL
198169
PyEval_InitThreads();
199170

200171
mPythonEnabled = true;
201172

202173
mMainModule = PyImport_AddModule( "__main__" ); // borrowed reference
203174
mMainDict = PyModule_GetDict( mMainModule ); // borrowed reference
175+
}
204176

205-
runString( "import sys" ); // import sys module (for display / exception hooks)
206-
runString( "import os" ); // import os module (for user paths)
207-
208-
// support for PYTHONSTARTUP-like environment variable: PYQGIS_STARTUP
209-
// (unlike PYTHONHOME and PYTHONPATH, PYTHONSTARTUP is not supported for embedded interpreter by default)
210-
// this is different than user's 'startup.py' (below), since it is loaded just after Py_Initialize
211-
// it is very useful for cleaning sys.path, which may have undesireable paths, or for
212-
// isolating/loading the initial environ without requiring a virt env, e.g. homebrew or MacPorts installs on Mac
213-
runString( "pyqgstart = os.getenv('PYQGIS_STARTUP')\n" );
214-
runString( "if pyqgstart is not None and os.path.exists(pyqgstart): execfile(pyqgstart)\n" );
215-
216-
#ifdef Q_OS_WIN
217-
runString( "oldhome=None" );
218-
runString( "if os.environ.has_key('HOME'): oldhome=os.environ['HOME']\n" );
219-
runString( "os.environ['HOME']=os.environ['USERPROFILE']\n" );
220-
#endif
177+
void QgsPythonUtilsImpl::finish() {
178+
// release GIL!
179+
// Later on, we acquire GIL just before doing some Python calls and
180+
// release GIL again when the work with Python API is done.
181+
// (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
182+
// around any calls to Python API, otherwise we may segfault!)
183+
_mainState = PyEval_SaveThread();
184+
}
221185

222-
// construct a list of plugin paths
223-
// plugin dirs passed in QGIS_PLUGINPATH env. variable have highest priority (usually empty)
224-
// locally installed plugins have priority over the system plugins
225-
// use os.path.expanduser to support usernames with special characters (see #2512)
226-
QStringList pluginpaths;
227-
foreach ( QString p, extraPluginsPaths() )
186+
bool QgsPythonUtilsImpl::checkQgisUser() {
187+
// import QGIS user
188+
QString error_msg = QObject::tr( "Couldn't load qgis.user." ) + "\n" + QObject::tr( "Python support will be disabled." );
189+
if ( !runString( "import qgis.user", error_msg ) )
228190
{
229-
if ( !QDir( p ).exists() )
230-
{
231-
QgsMessageOutput* msg = QgsMessageOutput::createMessageOutput();
232-
msg->setTitle( QObject::tr( "Python error" ) );
233-
msg->setMessage( QString( QObject::tr( "The extra plugin path '%1' does not exist !" ) ).arg( p ), QgsMessageOutput::MessageText );
234-
msg->showMessage();
235-
}
236-
#ifdef Q_OS_WIN
237-
p = p.replace( '\\', "\\\\" );
238-
#endif
239-
// we store here paths in unicode strings
240-
// the str constant will contain utf8 code (through runString)
241-
// so we call '...'.decode('utf-8') to make a unicode string
242-
pluginpaths << '"' + p + "\".decode('utf-8')";
191+
// Should we really bail because of this?!
192+
return false;
243193
}
244-
pluginpaths << homePluginsPath();
245-
pluginpaths << '"' + pluginsPath() + '"';
194+
return true;
195+
}
246196

247-
// expect that bindings are installed locally, so add the path to modules
248-
// also add path to plugins
249-
QStringList newpaths;
250-
newpaths << '"' + pythonPath() + '"';
251-
newpaths << homePythonPath();
252-
newpaths << pluginpaths;
253-
runString( "sys.path = [" + newpaths.join( "," ) + "] + sys.path" );
197+
void QgsPythonUtilsImpl::doUserImports() {
254198

255-
// import SIP
256-
if ( !runString( "import sip",
257-
QObject::tr( "Couldn't load SIP module." ) + "\n" + QObject::tr( "Python support will be disabled." ) ) )
258-
{
259-
exitPython();
260-
return;
261-
}
199+
QString startuppath = homePythonPath() + " + \"/startup.py\"";
200+
runString( "if os.path.exists(" + startuppath + "): from startup import *\n" );
201+
}
262202

263-
// set PyQt4 api versions
264-
QStringList apiV2classes;
265-
apiV2classes << "QDate" << "QDateTime" << "QString" << "QTextStream" << "QTime" << "QUrl" << "QVariant";
266-
foreach ( const QString& clsName, apiV2classes )
267-
{
268-
if ( !runString( QString( "sip.setapi('%1', 2)" ).arg( clsName ),
269-
QObject::tr( "Couldn't set SIP API versions." ) + "\n" + QObject::tr( "Python support will be disabled." ) ) )
270-
{
203+
void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
204+
{
205+
init();
206+
if (!checkSystemImports()){
271207
exitPython();
272208
return;
273-
}
274209
}
275-
276-
// import Qt bindings
277-
if ( !runString( "from PyQt4 import QtCore, QtGui",
278-
QObject::tr( "Couldn't load PyQt4." ) + "\n" + QObject::tr( "Python support will be disabled." ) ) )
279-
{
280-
exitPython();
281-
return;
282-
}
283-
284-
// import QGIS bindings
285-
QString error_msg = QObject::tr( "Couldn't load PyQGIS." ) + "\n" + QObject::tr( "Python support will be disabled." );
286-
if ( !runString( "from qgis.core import *", error_msg ) || !runString( "from qgis.gui import *", error_msg ) )
287-
{
288-
exitPython();
289-
return;
210+
// initialize 'iface' object
211+
runString( "qgis.utils.initInterface(" + QString::number(( unsigned long ) interface ) + ")" );
212+
if (!checkQgisUser()) {
213+
exitPython();
214+
return;
290215
}
216+
doUserImports();
217+
finish();
218+
}
291219

292-
// This is the main difference with initInterface() for desktop plugins
293-
// import QGIS Server bindings
294-
error_msg = QObject::tr( "Couldn't load PyQGIS Server." ) + "\n" + QObject::tr( "Python support will be disabled." );
295-
if ( !runString( "from qgis.server import *", error_msg ) )
296-
{
297-
exitPython();
298-
return;
299-
}
300220

221+
#ifdef HAVE_SERVER_PYTHON_PLUGINS
222+
void QgsPythonUtilsImpl::initServerPython( QgsServerInterface* interface )
223+
{
301224

302-
// import QGIS utils
303-
error_msg = QObject::tr( "Couldn't load QGIS utils." ) + "\n" + QObject::tr( "Python support will be disabled." );
304-
if ( !runString( "import qgis.utils", error_msg ) )
305-
{
306-
exitPython();
307-
return;
225+
init();
226+
if (!checkSystemImports()){
227+
exitPython();
228+
return;
308229
}
309-
310-
// tell the utils script where to look for the plugins
311-
runString( "qgis.utils.plugin_paths = [" + pluginpaths.join( "," ) + "]" );
312-
runString( "qgis.utils.sys_plugin_path = \"" + pluginsPath() + "\"" );
313-
runString( "qgis.utils.home_plugin_path = " + homePluginsPath() );
314-
315-
#ifdef Q_OS_WIN
316-
runString( "if oldhome: os.environ['HOME']=oldhome\n" );
317-
#endif
318-
319230
// This is the other main difference with initInterface() for desktop plugins
320231
runString( "qgis.utils.initServerInterface(" + QString::number(( unsigned long ) interface ) + ")" );
321-
322-
QString startuppath = homePythonPath() + " + \"/startup.py\"";
323-
runString( "if os.path.exists(" + startuppath + "): from startup import *\n" );
324-
325-
// release GIL!
326-
// Later on, we acquire GIL just before doing some Python calls and
327-
// release GIL again when the work with Python API is done.
328-
// (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
329-
// around any calls to Python API, otherwise we may segfault!)
330-
_mainState = PyEval_SaveThread();
232+
if (!checkQgisUser()){
233+
exitPython();
234+
return;
235+
}
236+
doUserImports();
237+
finish();
331238
}
332239

333240
bool QgsPythonUtilsImpl::startServerPlugin( QString packageName )

‎src/python/qgspythonutilsimpl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ class QgsPythonUtilsImpl : public QgsPythonUtils
4545
bool startServerPlugin( QString packageName ) override;
4646
#endif
4747

48+
// functions that do the initialization work
49+
bool checkSystemImports();
50+
bool checkQgisUser();
51+
void doUserImports();
52+
void init();
53+
void finish();
54+
4855
//! close python interpreter
4956
void exitPython() override;
5057

0 commit comments

Comments
 (0)
Please sign in to comment.