12

I've come across a weird issue while running standalone PyQGIS processing scripts. The order of imports in the script affects its normal execution.

You can reproduce the problem by opening a Python console and entering the following script (I use GNU/Linux, QGIS 2.6.1, processing plugin v.2.2.0-2, and Python 2.7.3):

# Prepare the environment
import sys
from qgis.core import QgsApplication
from PyQt4.QtGui import QApplication
app = QApplication([])
QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()

# Prepare processing framework 
sys.path.append('/home/YOUR_USER/.qgis2/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()

print Processing.getAlgorithm("qgis:creategrid")

# Exit applications
QgsApplication.exitQgis()
QApplication.exit()

You should obtain:

ALGORITHM: Create grid
    HSPACING <ParameterNumber>
    VSPACING <ParameterNumber>
    WIDTH <ParameterNumber>
    HEIGHT <ParameterNumber>
    CENTERX <ParameterNumber>
    CENTERY <ParameterNumber>
    GRIDTYPE <ParameterSelection>
    CRS <ParameterCrs>
    SAVENAME <OutputVector>

On the other hand, if you switch the order of imports (lines 3 and 4), this way:

from PyQt4.QtGui import QApplication
from qgis.core import QgsApplication

the script now returns... None, because the algorithm was not found.

This issue implies that you cannot run processing algorithms out of QGIS if you (by chance) write imports in the wrong order.

I've checked in StackOverflow but according to Does Python import order matter, the order shouldn't really matter. Moreover, the Style Guide for Python Code tells us to import standard (more generic) libraries first, then related third party libraries, and finally, local application specific imports. I think PyQt4 lies in the 2nd category of imports, whereas PyQGIS would be local application specific, so PyQt4 imports should come first (I'm not an expert on this, though).

Do you have an idea of why this could happen? Have you ever experienced something similar?


EDIT 1: Changed implicit imports (from abc import *) by explicit ones (e.g., from abc import xyz) as suggested by @mike-t.

  • 2
    Just wanted to say, excellent question with a short reproducible example and evidence of research and analysis of that research. – user2856 Jan 21 '15 at 1:29
13

tl;dr

import qgis
import PyQt4
etc

is the correct way

Long version

Yes the import order can matter and in the case of QGIS 2.0 and above it does matter.

You should always import qgis.core or qgis.gui, even just import qgis is enough, before you import any PyQt stuff.

That seems silly. Why?

In QGIS 2.0 we switched to using version 2 bindings of SIP which made API calls more Python like e.g it will auto convert types for you:

1.0 SIP you had to do:

value.toString()

in 2.0

value

will just work if it's a string type in the C++ code.

Ok So what

The kicker is that we have to set the API version to 2 in code before it gets set my something else, you can't set it again once it's been set. If you import PyQt first it will set the value to v1 but everything in QGIS now uses v2. In order to fix this we set it to v2 in qgis.__init__.py but we have to import qgis first or else PyQt wins.

Because all of the plugins in QGIS 2.0 and above now use SIP v2 any SIP v1 like calls will generate a error when running.

  • 1
    Thank you Nathan, I was not aware of such implications. I wonder if this issue is well documented for PyQGIS developers. For instance, this shows how a plugin should look like, and does not mention anything about imports. I guess this issue doesn't affect plugins in the same way it affects standalone applications/scripts, though. (I'll upvote your answer in some minutes, I've spent all the daily votes already :)). – Germán Carrillo Jan 20 '15 at 23:46
  • Yes it doesn't effect plugins because we import qgis in c++ before PyQt. – Nathan W Jan 21 '15 at 1:01
  • Strange...I get an "ImportError: No module named PyQt" when using import PyQt although import qgis works. Not that it bothers me to the point that I need to ask a new question, was just wondering if you know why this is. I use Windows 7 with the same processing/python versions as @gcarrillo. – Joseph Jan 22 '15 at 10:51
  • That is a typo by me. See edit. – Nathan W Jan 22 '15 at 10:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.