5

I am new to the PyQGIS API.

For developing I use my Spyder IDE with QGIS and GRASS modules. In order to make my script executable I just run my code with the QGIS python.exe in my bat file. This all works so far. However, none of the PyQGIS cookbook code snippets worked and for some reason the only thing that did the job was this example I could adapt (posted several times by user @Germán Carrillo). Also it took me quite a while to figure out that the order how you import your modules matters (PyQt4.QtGui before qgis.core breaks the code).

So for example I want to create a simple hillshade from a DEM. This works with my code from my Spyder IDE if I run it once. When I run it another time, it causes python to stop working. When I run it as a bat file, I still get the hillshade, but again I get the message 'python.exe has stopped working'. This is not clean and helpfull at all if I want to develop something more complex and let it run in an automated way. This answer didn't work for me unfortunately. Also, either way the processing module copies its folder structure (only the folders though, not its content) into my working directory together with a qgis-auth.db file. This also seems not clean at all.

Here my code with a download link provided to a small DEM sample file:

# get small DEM from https://github.com/GeospatialPython/Learn/blob/master/dem.zip

# Prepare the environment
import sys
from qgis.core import *
from PyQt4.QtGui import *
app = QApplication([], True)
QgsApplication.setPrefixPath("C:/OSGeo4W64/apps/qgis", True)
QgsApplication.initQgis()
print "QGIS successfully Initialised"

# Prepare processing framework 
# https://gis.stackexchange.com/questions/129513/how-can-i-access-processing-with-python
sys.path.append('C:/OSGeo4W64/apps/qgis/python/plugins') # Folder where Processing is located
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import *

# Write your code here to load some layers, use processing algorithms, etc.
rasterLyr = QgsRasterLayer("dem.asc", "hillshade")
rasterLyr.isValid()

general.runalg("gdalogr:hillshade", rasterLyr, 1, False, False, 1.0, 1.0, 315.0, 45.0,"qgis_hs.tif")

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

Again, this code work in my Spyder IDE when run once, but causes python to stop working when run another time. It also works when run from a bat file, but also crashes my python.exe. Any ideas? That way I can't replace ArcPy with PyQGIS unfortunately.


The problem definitely seems to be related to how QApplication and QgsApplication is initialised (or not correctly ended?). I just tried an NDVI calculation without the messy processing library and I still get the same crashing errors.


Yes, most definitely a Qt problem that is caused by not properly closing the app. This was reported quite frequently. Unfortunately, none of the proposed solutions work for me (or I just don't know how to implement correctly).

0

1 Answer 1

4

The problem definitely seems to be related to how QApplication and QgsApplication is initialised

Yes, the thing is: QgsApplication is a subclass of PyQt's QApplication, so basically you do not need (and should not) instantiate a QApplication here, instead just use the QgsApplication.

The problem can also be related to the QgsApplication.exitQgis() as it seems to cause a sigsegv on the exit. Using QgsApplication.exit() solve it for me

Try this:

import sys
# Import only what you're going to use
from qgis.core import QgsApplication, QgsRasterLayer

# You can add this path to your system's environment so you don't have to type it here
sys.path.append('C:/OSGeo4W64/apps/qgis/python/plugins')
import processing

# This is a 'fake' iface since we are not using a interface here
class DummyIface(object):

    def __init__(self):
        self.destCrs = None


# Pass QgsApplication to an object and you can use it just like a QApplication
app = QgsApplication([], True)
app.initQgis()
print "QGIS successfully Initialised"

# I took the freedom to change the way you used processing here, just to be sure it will work
processing.classFactory(DummyIface())

rasterLyr = QgsRasterLayer("dem.asc", "hillshade")
# An assertion check, because we do not want to continue if we do not have this layer right
assert rasterLyr.isValid()

processing.runalg("gdalogr:hillshade", rasterLyr, 1, False, False, 1.0, 1.0, 315.0, 45.0,"qgis_hs.tif")

app.exit()

sidenote: you may have problems with the processing module as it tries to set a progress for you while you have no interface. Have a look at this question if that is the case

1
  • Thanks for your reply! I'll just sit it out and use GDAL in the meantime...apparently QGIS 3.0 should make using PyQGIS much less of a hassle: nyalldawson.net/2017/05/…
    – GeoEki
    Dec 2, 2017 at 13:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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