2

I purchased this book called Building Mapping Applications with QGIS and I am trying to work through one of the exercises. There is one script that I try to run that crashes python, generating the error message "python.exe has stopped working".

import sys
import os
from qgis.core import *
from qgis.gui import *
from PyQt4.QtGui import *
from PyQt4.QtCore import Qt



#############################################################################


class MapViewer(QMainWindow):
    def __init__(self, shapefile):
        QMainWindow.__init__(self)
        self.setWindowTitle("Map Viewer")

        canvas = QgsMapCanvas()
        canvas.useImageToRender(False)
        canvas.setCanvasColor(Qt.white)
        canvas.show()

        layer = QgsVectorLayer(shapefile, "layer1", "ogr")
        if not layer.isValid():
            raise IOError("Invalid shapefile")

        QgsMapLayerRegistry.instance().addMapLayer(layer)
        canvas.setExtent(layer.extent())
        canvas.setLayerSet([QgsMapCanvasLayer(layer)])

        layout = QVBoxLayout()
        layout.addWidget(canvas)

        contents = QWidget()
        contents.setLayout(layout)
        self.setCentralWidget(contents)

#############################################################################


def main():
    """  Our main program.
    """
    QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'], True)
    QgsApplication.initQgis()

    app = QApplication(sys.argv)

    viewer = MapViewer("/path/to/shapefile.shp")
    viewer.show()

    app.exec_()

    QgsApplication.exitQgis()

#############################################################################

if __name__ == "__main__":
    main()

I don't know a whole lot about Python with QGIS so I'm not too sure what is causing python to crash. I am positive that all of the modules are importing correctly because if I define my paths and then import the modules in the script using the OSGeo4W Shell, there are no error messages.

This is how my paths are defined:

SET OSGEO4W_ROOT=C:\OSGeo4W64
SET QGIS_PREFIX=%OSGEO4W_ROOT%\apps\qgis
SET PATH=%PATH%;%QGIS_PREFIX%\bin
SET PYTHONPATH=%QGIS_PREFIX%\python;%PYTHONPATH%

Given all of this, I think there has to be something wrong in the script. However, when I check the script using http://pep8online.com/ there are no errors that I can fix that will result in python not crashing.

  • 1
    try SET PATH=%QGIS_PREFIX%\bin;%PATH%, perhaps the string is too long. Is QGIS working? you can open that application can't you... How are you running the script? is it in a python shell, at command prompt etc.. have you supplied the arguments that the script is expecting? – Michael Stimson Jun 21 '16 at 1:02
  • The SET PATH suggestion did not solve the issue. QGIS works and opens. The script is being run through OSGeo4W shell using python "C:\script.py" after I set the 4 paths. I am not sure about the arguments part. – ge0m3try Jun 21 '16 at 1:35
  • Could it be that layer = QgsVectorLayer(shapefile, "layer1", "ogr") needs to reference an actual shapefile? Or maybe viewer = MapViewer("/path/to/shapefile.shp") needs to be changed? – ge0m3try Jun 21 '16 at 1:38
  • the layer is fine, it's saying 'make a layer from shapefile and call it "layer1"' but the path to shapefile does need to be set to a real shapefile for the viewer, edit that part to your shapefile path and see if it still crashes. – Michael Stimson Jun 21 '16 at 1:59
  • 1
    It's a colon, it's used to start a block which is why it went to indent (block). I can't see that I can be of any more help here.. if there's an error it's not obvious, perhaps it's a difference of version between the book and your installed version. Try posting on Stack Overflow; this seems to be more of a python problem than GIS, the users there might be able to help to a greater depth with python. – Michael Stimson Jun 22 '16 at 1:06
3

I was fortunate enough to get in touch with the author of the book so I will share his response here:

I suspect I may know what the problem is...after looking at this reader's problems in more depth, I've discovered that something has changed in newer versions of QGIS, and the example code no longer works as it is written. In technical terms, it seems that you now need to instantiate the QApplication object before making the call to QgsApplication.initQgis() -- the example program in the book instantiates the QApplication object after calling QgsApplication.initQgis(), which causes the program to crash. To fix this, change the main() function to look like the following:

def main():
    """  Our main program.
    """
    app = QApplication(sys.argv)
    QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'],True)
    QgsApplication.initQgis()

    viewer = MapViewer("C:/folder/shapefile.shp")
    viewer.show()

    app.exec_()

    QgsApplication.exitQgis()

As you can see, I've moved the "app = QApplication(sys.argv)" line to the top.

Important Note: Make sure that forward slashes are used in viewer = MapViewer("C:/folder/shapefile.shp") - using a backslash will result in an error message stating that the shapefile is invalid.

I also thought it would be worth mentioning that none of the above fixes (comments on the question) were necessary. So, the script will work if the paths are defined as follows:

SET OSGEO4W_ROOT=C:\OSGeo4W64
SET QGIS_PREFIX=%OSGEO4W_ROOT%\apps\qgis
SET PATH=%PATH%;%QGIS_PREFIX%\bin
SET PYTHONPATH=%QGIS_PREFIX%\python;%PYTHONPATH%

Then, the entire script looks like this:

import sys
import os
from qgis.core import *
from qgis.gui import *
from PyQt4.QtGui import *
from PyQt4.QtCore import Qt



#############################################################################


class MapViewer(QMainWindow):
    def __init__(self, shapefile):
        QMainWindow.__init__(self)
        self.setWindowTitle("Map Viewer")

        canvas = QgsMapCanvas()
        canvas.useImageToRender(False)
        canvas.setCanvasColor(Qt.white)
        canvas.show()

        layer = QgsVectorLayer(shapefile, "layer1", "ogr")
        if not layer.isValid():
            raise IOError("Invalid shapefile")

        QgsMapLayerRegistry.instance().addMapLayer(layer)
        canvas.setExtent(layer.extent())
        canvas.setLayerSet([QgsMapCanvasLayer(layer)])

        layout = QVBoxLayout()
        layout.addWidget(canvas)

        contents = QWidget()
        contents.setLayout(layout)
        self.setCentralWidget(contents)

#############################################################################


def main():
    """  Our main program.
    """
    app = QApplication(sys.argv)
    QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'],True)
    QgsApplication.initQgis()

    viewer = MapViewer("C:/folder/shapefile.shp")
    viewer.show()

    app.exec_()

    QgsApplication.exitQgis()

#############################################################################

if __name__ == "__main__":
    main()

Execute it in the OSGEO4W Shell using the following command:

python "C:\script.py"

Lastly, note that at the time of this writing, the script works properly and launches a viewer showing the shapefile referenced, but returns a few errors in the shell that do not seem to be problematic:

ERROR: Opening of authentication db FAILED
ERROR: Unable to establish authentication database connection
ERROR: Auth db could not be created and opened
QSqlDatabasePrivate::database: unable to open database: "unable to open database file Error opening database"
ERROR: Opening of authentication db FAILED

Much thanks to the author Erik Westra for providing me with this solution.

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.