Home Programming QGIS Python Programming Cookbook, Second Edition - Second Edition

QGIS Python Programming Cookbook, Second Edition - Second Edition

By Joel Lawhead
books-svg-icon Book
eBook $43.99 $29.99
Print $54.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $43.99 $29.99
Print $54.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Automating QGIS
About this book
QGIS is a desktop geographic information system that facilitates data viewing, editing, and analysis. Paired with the most efficient scripting language—Python, we can write effective scripts that extend the core functionality of QGIS. Based on version QGIS 2.18, this book will teach you how to write Python code that works with spatial data to automate geoprocessing tasks in QGIS. It will cover topics such as querying and editing vector data and using raster data. You will also learn to create, edit, and optimize a vector layer for faster queries, reproject a vector layer, reduce the number of vertices in a vector layer without losing critical data, and convert a raster to a vector. Following this, you will work through recipes that will help you compose static maps, create heavily customized maps, and add specialized labels and annotations. As well as this, we’ll also share a few tips and tricks based on different aspects of QGIS.
Publication date:
March 2017
Publisher
Packt
Pages
464
ISBN
9781787124837

 

Chapter 1. Automating QGIS

In this chapter, we will focus on the tools needed to write Python scripts for the PyQGIS framework. We will cover the following recipes:

  • Installing QGIS 2.18 for development

  • Using the QGIS Python console for interactive control

  • Automatically starting the Python console

  • Using Python's Script Runner plugin

  • Setting up your QGIS IDE

  • Debugging QGIS Python scripts

  • Navigating the PyQGIS API

  • Creating a traditional QGIS plugin

  • Creating a Processing Toolbox plugin

  • Distributing a plugin

  • Building a standalone application

  • Storing and reading global preferences

  • Storing and reading project preferences

  • Accessing the script path from within your script

 

Introduction


This chapter explains how to automate QGIS using Python. In addition to setting this up, we will also configure the free Eclipse Integrated Development Environment (IDE) along with the PyDev plugin to make writing, editing, and debugging scripts easier. We will also learn the basics of different types of QGIS Python scripts through the PyQGIS API. Finally, we'll examine some core QGIS plugins that significantly extend its capability.

 

Installing QGIS 2.18 for development


QGIS has a set of Python modules and libraries that can be accessed from the Python console within it. However, they can also be accessed from outside QGIS to write standalone applications. First, you must make sure that PyQGIS is installed on your platform, then set up some required environment variables.

In this recipe, we will walk you through the additional steps required beyond the normal installation process to prepare your system for development. The steps for each platform are provided, which also include the different styles of Linux package managers. The version of QGIS in your Linux package manager may be older. You can find additional detailed installation instructions at https://www.qgis.org/en/site/forusers/alldownloads.html.

Getting ready

QGIS uses different installation methods for Windows, GNU/Linux, and Mac OS X. The Windows installer installs everything you need for Python development, including Python itself.

However, on both Linux distributions and Mac OS X, you may need to manually install the Python modules to complete the installation process. On Mac OS X, you can download installers for some commonly used Python modules with QGIS; refer to http://www.kyngchaos.com/software/python.

How to do it...

On Linux, you have an option to either compile from the source or just specify the Python interface to be installed through your package manager.

Installing PyQGIS using the Debian package manager

  1. For Linux distributions based on the Debian Linux package manager, which includes Ubuntu and Debian, use the following command in a shell:

      sudo apt-get update
    
  2. Next, install the QGIS, PyQGIS, and QGIS GRASS plugins:

      sudo apt-get install qgis python-qgis qgis-plugin-grass
    

Installing PyQGIS using the RPM package manager

  1. For Linux distributions based on the Red Hat Package Manager (RPM), first update the package manager as follows:

      sudo yum update
    
  2. Then, install the packages for the QGIS, PyQGIS, and QGIS GRASS plugins:

     sudo yum install qgis qgis-python qgis-grass
    

Setting the environment variables

Now we need to set PYTHONPATH to the PyQGIS directory. At the same time, append the path to this directory to the PATH variable so that you can use the PyQGIS modules with an external IDE.

Setting the environment variables on Windows

  1. Set the PYTHONPATH variable in a command prompt to the bin directory of the QGIS installation:

      set PYTHONPATH="C:\Program Files\QGIS 2.18\bin"
    
  2. Next, append QGIS's bin directories to the system's PATH variable:

      set PATH="C:\Program Files\QGIS 2.18\bin";"C:\Program Files\QGIS
          2.18";%PATH%
    

Setting environment variables on Linux

  1. Set the PYTHONPATH variable in a command prompt to the bin directory of the QGIS installation:

      export PYTHONPATH=/usr/share/qgis/python
    
  2. Now append the QGIS shared library directory to a runtime search path. Note that this location can vary depending on your system configuration:

      export LD_LIBRARY_PATH=/usr/share/qgis/python
    

How it works...

The QGIS installation process and package managers set up the Python module's configuration in a way that it becomes internal to QGIS. When you use the Python console inside QGIS, it knows where all the PyQGIS modules are. However, if you want to use the PyQGIS API outside it by using a system Python installation on either Windows or Linux, it would be necessary for you set some system variables so that Python could find the required PyQGIS modules.

There's more...

This recipe uses the default QGIS paths on each platform. If you aren't sure which PyQGIS path is for your system, you can figure this out from the Python console in QGIS.

Finding the PyQGIS path on Windows

The libraries on Windows, as opposed to other platforms, are stored in a different location. To locate the path, you need to check the current working directory of the Python console:

  1. Start QGIS.

  2. Select Python Console from the Plugins menu, which will appear in the lower-right corner of the QGIS application window, as shown in the following screenshot. You can also use the keyboard shortcut Control + Alt + P to do this:

  3. Use the os module to get the current working directory:

            import os 
            os.getcwd() 
    
  4. Verify that the current working directory of the Python console is returned.

Finding the location of the QGIS Python installation on other platforms

Perform the following steps to find the path needed for this recipe on all the other platforms:

  1. Start QGIS.

  2. Start the QGIS Python console.

  3. Use the sys module to locate the PyQGIS path

            import sys 
            sys.path 
    
  4. Python will return a list of paths.

  5. Find the path that ends in /python, which is the location of the Python installation used by QGIS.

 

Using the QGIS Python console for interactive control


The Python console allows you to interactively control QGIS; you can test out ideas or just do some quick automation. The console is the simplest way to use the API.

How to do it...

In the following steps, we'll open the console, create a vector layer in the memory, and display it on the map:

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. The following code will create a point on the map canvas:

            layer =  QgsVectorLayer('Point?crs=epsg:4326','MyPoint',"memory") 
            pr = layer.dataProvider() 
            pt = QgsFeature() 
            point1 = QgsPoint(20,20) 
            pt.setGeometry(QgsGeometry.fromPoint(point1)) 
            pr.addFeatures([pt]) 
            layer.updateExtents() 
            QgsMapLayerRegistry.instance().addMapLayers([layer]) 
    

How it works...

This example uses a memory layer to avoid interacting with any data on either a disk or a network so as to keep things simple. Notice that when we declare the layer type, we add the parameter for the coordinate reference system (CRS) as EPSG:4326. Without this declaration, QGIS will prompt you to choose one. There are three parts, or levels, of abstraction even to create a single point on the map canvas, as shown here:

  1. First, create a layer that is of the type geometry. Next, reference a data provider to accept the data source.

  2. Then, create a generic feature object, followed by the point geometry.

  3. Next, we add the feature to the layer via the underlying data provider, then add the layer to the map canvas.

The layer type is memory, meaning that you can define the geometry and attributes in the code itself rather than an external data source. In this recipe, we just define the geometry and skip defining any attributes.

 

Automatically starting the Python console


As you become familiar with programming QGIS using Python, you'll want the Python console to always be available in QGIS. So, in this recipe, we'll add a Python startup script to QGIS to make sure the console starts when QGIS does.

Getting ready

First, you need the startup.py file, which QGIS will read at startup. You'll be able to use this file to customize different aspects of QGIS:

  1. In your user directory, locate the hidden .qgis2 folder.

  2. Your user folder is typically located in ~/.qgis2 on Linux and OSX and C:\Users\<username>\.qgis2 on Windows, which you can also access the %USERPROFILE% environment variable.

  3. Create a Python file named startup.py.

How to do it...

  1. Open the startup.py file you created.

  2. Add the following lines to it:

            from console import console 
            console.console_show() 
    

How it works...

When QGIS starts, it looks for a Python script named startup.py in the user's folder and executes any code it finds there. If you have an error in the file, QGIS will display an error dialog and disable Python within QGIS.

 

Using the Python's Script Runner plugin


The QGIS Python Script Runner plugin provides a middle ground for QGIS automation, between the interactive console and the overhead of plugins. It provides a script management dialog that allows you to easily load, create, edit, and run scripts for large-scale QGIS automation.

Getting ready

Install the Script Runner plugin using the QGIS plugin manager. Then, run the plugin from the Plugin menu to open the Script Runner dialog. Configure a default editor to edit the scripts using the following steps:

  1. Find the gear icon that represents the Script Runner Preferences settings dialog box and click on it.

  2. In the General Options section, check the Edit scripts using: checkbox.

  3. Click on the ... button to navigate to the location of a text editor on your system.

  4. Click on the Open button.

  5. Click on the OK button in the Preferences dialog.

How to do it...

  1. In the Script Runner dialog, click on the New Script icon, as shown in the following screenshot:

  2. Navigate to the directory where you wish to save and name your script.

  3. Verify that the new script is loaded in Script Runner.

  4. Right-click (or control-click on a Mac) on the script name in Script Runner and select Edit script in external editor.

  5. In the editor, replace the template code with the following code:

            from PyQt4.QtCore import * 
            from PyQt4.QtGui import * 
            from qgis.core import * 
            from qgis.gui import * 
     
            def run_script(iface): 
                layer =  QgsVectorLayer('Polygon?crs=epsg:4326', 'Mississippi',
                                        "memory") 
                pr = layer.dataProvider() 
                poly = QgsFeature() 
                geom = QgsGeometry.fromWkt("""POLYGON ((-88.82 34.99, 
                                                        -88.09 34.89, 
                                                        -88.39 30.34, 
                                                        -89.57 30.18, 
                                                        -89.73 31, 
                                                        -91.63 30.99, 
                                                        -90.87 32.37, 
                                                        -91.23 33.44, 
                                                        -90.93 34.23, 
                                                        -90.30 34.99, 
                                                        -88.82 34.99))""") 
                poly.setGeometry(geom) 
                pr.addFeatures([poly]) 
                layer.updateExtents() 
                QgsMapLayerRegistry.instance().addMapLayers([layer]) 
    
  6. Click on the Run Script icon, which is represented by a green-colored arrow.

  7. Close the Script Runner plugin.

  8. Verify that the memory layer polygon is added to the QGIS map, as shown in the following screenshot:

How it works...

Script Runner is a simple but powerful idea. It allows you to build a library of automation scripts and use them from within QGIS without the overhead of building a plugin or a standalone application. All the Python and system path variables are set correctly and inherited from QGIS; however, you must still import the QGIS and Qt libraries.

There's more...

The Script Runner plugin makes managing lots of scripts easier. But there is also a script editor built into the PyQGIS console. This editor is a panel in the QGIS interface that you can use to create, edit, and run scripts. You can trigger the editor using the fourth icon from the left on the PyQGIS console toolbar.

 

Setting up your QGIS IDE


The Eclipse IDE and the PyDev plugin are cross-platform and free, and they possess advanced debugging tools.

Note

You can refer to http://pydev.org/manual_101_install.html in order to install PyDev correctly.

This tool makes an excellent PyQGIS IDE. Eclipse allows you to have multiple Python interpreters configured for different Python environments. When you install PyDev, it automatically finds the Python installations. On Windows, you also need to add the Python interpreter, installed with PyQGIS. On all platforms, you must tell PyDev where the PyQGIS libraries are.

Getting ready

This recipe uses Eclipse and PyDev. You can use the latest version of both the packages supported by your operating system. All platforms, except for Windows, rely on the Python interpreter. This means that there is an extra step in Windows to add the Python interpreter.

How to do it...

The following steps will walk you through the process of adding the QGIS-specific Python interpreter to Eclipse in order to support the running standalone QGIS applications or the debugging of QGIS plugins.

Adding the Python interpreter to Windows

The process used to add a Python interpreter to Eclipse on Windows is different from the process used on Linux. The following steps describe how to set up the interpreter on the Windows version of Eclipse:

  1. Open Eclipse.

  2. From the Window menu, select Preferences.

  3. In the pane on the left-hand side of the Preferences window, click on the arrow icon next to PyDev.

  4. From the list of PyDev preferences, select Interpreters.

  5. In the pane labeled Python Interpreters, click on the New button.

  6. In the Select interpreter dialog, name the interpreter PyQGIS.

  7. Navigate to the location of the Python interpreter called python.exe, placed within the bin folder of the QGIS program folder. On OS X and Linux, you use the system's Python installation. On Windows, Python is included with QGIS. The default location on Windows is C:\Program Files\QGIS2.18\bin\python.exe, as shown in the following screenshot:

  8. When you click on the OK button, Eclipse will attempt to automatically add every Python library it finds to the Python path to configure this interpreter. We need to control which libraries are added to prevent conflicts. Click on the Deselect All button and then click on OK:

  9. Eclipse will issue a warning dialog because you haven't selected any core libraries. Click on the Proceed anyways button, as shown here:

Adding the PyQGIS module paths to the interpreter

Apart from adding the Python interpreter, you also need to add the module paths needed by PyQGIS, using the following steps. These steps will require you to switch back and forth between QGIS and Eclipse.

  1. Start QGIS.

  2. Select Python Console from the Plugins menu.

  3. Use the sys module to locate the PyQGIS Python path, as described in the previous recipe, Setting the environment variables:

            import sys 
            sys.path 
    
  4. We also want to add the PyQGIS API so the script has access to all of the QGIS functions within Eclipse. Next, find that path using the QGIS Python Console by typing the following command:

          qgis
    
  5. For each path in the returned list, click on the New Folder button in Eclipse's Libraries pane for your QGIS interpreter and browse to that folder until all the paths have been added. If a given folder does not exist on your system, simply ignore it, as shown here:

  6. Click on the OK button in the Preferences dialog.

Adding the PyQGIS API to the IDE

To take full advantage of Eclipse's features, including code completion, we will add the QGIS and Qt4 modules to the PyQGIS Eclipse interpreter preferences. The following steps will allow Eclipse to suggest the possible methods and properties of QGIS objects as you type; this feature is known as autocomplete:

  1. In the PyDev preferences for the PyQGIS interpreter, select the Forced Builtins tab, as shown in the following screenshot:

  2. Click on the New button.

  3. In the Builtin to add dialog, type qgis:

  4. Click on the OK button.

Adding environment variables

You will also need to create a PATH variable that points to the QGIS binary libraries, DLLs on Windows, and other libraries needed by QGIS at runtime. And you'll need to create this on all platforms in the following way:

  1. In the PyDev preferences dialog, ensure that the PyQGIS interpreter is selected from the list of interpreters.

  2. Select the Environment tab.

  3. Click on the New button.

  4. In the Name field, enter PATH.

  5. For the Value field, add the path to the QGIS program directory and to any QGIS directories that contain binaries separated by a semicolon. The following is an example from a Windows machine:

      C:\Program Files\QGIS 2.18;C:\Program Files\QGIS 2.18\bin;
          C:\Program Files\QGIS 2.18\apps\qgis\bin;C:\Program Files\QGIS
          2.18\apps\Python27\DLLs
    

How it works...

Eclipse and PyDev use only the information you provide to run a script in the Eclipse workspace. This approach is very similar to the popular Python tool virtualenv, which provides a clean environment when writing and debugging code to ensure that you don't waste time troubleshooting issues caused by the environment.

 

Debugging QGIS Python scripts


In this recipe, we will configure Eclipse to debug QGIS Python scripts. This setup will allow you to interactively watch the execution of programs as well as pause the execution as needed. This kind of interactive debugging is particularly useful in a GUI program such as QGIS because in addition to the user interface, there are program functions happening behind the scenes. Debugging programs that have processes in the foreground and background can be extremely difficult. This interactive debugging approach makes the development of complex applications such as these much more efficient by stepping through each part of the program as it is executed. You can see what is happening in real time and troubleshoot more easily.

How to do it...

Both QGIS and Eclipse must be configured for debugging so that the two pieces of software can communicate. Eclipse attaches itself to QGIS in order to give you insights into the Python scripts running in QGIS. This approach allows you to run scripts in a controlled way that can pause the execution while you monitor the program to catch bugs as they occur.

Configuring QGIS

The following steps will add two plugins to QGIS; this will allow Eclipse to communicate with QGIS. The first plugin, Plugin Reloader, allows you to reload a QGIS plugin into the memory without restarting QGIS for faster testing. The second plugin, Remote Debug, connects QGIS to Eclipse. Remote Debug is an experimental plugin, so we must ensure that experimental plugins are visible to the QGIS plugin manager in the list of the available plugins. This can be done in the following way:

  1. Start QGIS.

  2. Under the Plugins menu, select Manage and Install Plugins...

  3. In the left pane of the Plugins dialog, select the Settings tab.

  4. Scroll down the Settings window and ensure that the Show also experimental plugins checkbox is checked, as shown in the following screenshot:

  5. Click on the OK button.

  6. Select the tab labeled All in the pane on the left-hand side of the Plugins window.

  7. In the Search dialog at the top of the window, search for Plugin Reloader.

  8. Select Plugin Reloader from the search results and then click on the Install Plugin button.

  9. Next, search for the Remote Debug plugin and install it as well.

  10. Finally, install the HelloWorld plugin too.

Configuring Eclipse

Now that QGIS is configured for debugging in Eclipse, we will configure Eclipse to complete the debugging communication loop, as shown in the following steps:

  1. Start Eclipse.

  2. In the File menu, select New and then click on Project.

  3. Select General and then click on Project from the New Project dialog.

  4. Click on the Next> button.

  5. Give the project the name HelloWorld Plugin.

  6. Click on the Finish button.

  7. Select the new HelloWorld plugin project in the project explorer window and select New. Then, click on Folder from the File menu.

  8. In the New Folder dialog, click on the Advanced>> button.

  9. Choose the Link to alternate location (Linked Folder) radio button.

  10. Click on the Browse button and browse to the location of the HelloWorld plugin folder.

    Tip

    You can find the location of the HelloWorld plugin from within the QGIS plugin manager, as shown in the following screenshot:

  11. Click on the Finish button.

Testing the debugger

In the previous parts of this recipe, we configured Eclipse and QGIS so they could work together to debug QGIS plugins. In this section, we will test the configuration using the simplest possible plugin, HelloWorld, to run Eclipse using the Debug Perspective. We will set up a breakpoint in the plugin to pause the execution and then monitor the plugins execution from within Eclipse, as follows:

  1. Under the HelloWorld folder, open the HelloWorld.py file.

  2. From the Eclipse Window menu, select Open Perspective and then click on Other....

  3. From the Open Perspective dialog, select Debug.

  4. Click on the OK button.

  5. Scroll to the first line of the hello_world() function and double-click on the left-hand side of the line number to set a breakpoint, which is displayed as a green-colored icon:

  6. From the Pydev menu, select Start Debug Server.

  7. Verify that the server is running by looking for a message in the Debug console at the bottom of the window, similar to the following:

    Debug Server at port: 5678
    
  8. Switch over to QGIS.

  9. From the QGIS Plugins menu, select Remote Debug and then select the Remote Debug command.

  10. Verify that the QGIS status bar in the lower-left corner of the window displays the following message:

    Python Debugging Active
    
  11. Now select HelloWorld from the QGIS Plugins menu and then select HelloWorld.

  12. Switch back to Eclipse.

  13. Verify that the hello_world() function is highlighted at the breakpoint.

  14. From the Run menu, select Resume.

  15. Switch back to QGIS.

  16. Verify that the HelloWorld dialog box has appeared.

How it works...

The Remote Debug plugin acts as a client to the PyDev debug server in order to send the Python script's execution status from QGIS to Eclipse. While it has been around for several versions of QGIS now, it is still considered experimental.

The Plugin Reloader plugin can reset plugins that maintain the state as they run. The HelloWorld plugin is so simple that reloading is not needed to test it repeatedly. However, as you debug more complex plugins, you will need to run it in order to reset it before each test. This method is far more efficient and easier to use than closing QGIS, editing the plugin code, and then restarting it.

Note

You can find out more about debugging QGIS, including using other IDEs, at http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/ide_debugging.html.

 

Navigating the PyQGIS API


The QGIS Python API, also known as PyQGIS, allows you to control virtually every aspect of QGIS. The ability to find the PyQGIS object you need in order to access a particular feature of QGIS is critical to automation.

Getting ready

The PyQGIS API is based on the QGIS C++ API. The C++ API is kept up to date online and is well documented.

Note

The QGIS API's web page is located at https://qgis.org/api/modules.html.

The PyQGIS API documentation is not updated frequently because it is nearly identical to the structure of the C++ API. A tool named SWIG, which creates wrappers for multiple languages for C++ libraries, is used to create the PyQGIS API, making the documentation for the C++ API highly applicable for argument types and order. However, the QGIS project on https://github.com/ maintains a list of all the PyQGIS classes for the latest version. The PyQGIS APIs for different versions are located at https://github.com/qgis/QGIS/blob/master/python/qsci_apis/.

You can locate the documented class in the main C++ API and read about it. Then, look up the corresponding Python module and class using the PyQGIS API listing. In most cases, the C++ API name for a class is identical to that in Python. You should note that the PyQGIS versions are tracked separately from the QGIS version and have different version numbers.

In this recipe, we'll locate the PyQGIS class that controls labels in QGIS.

How to do it...

We will perform the following steps to see in which PyQGIS module the QGIS Label object and Qgs Label are located:

  1. Go to the QGIS API page at http://qgis.org/api/index.html.

  2. Click on the Modules tab.

  3. Click on the link QGIS core library.

  4. Scroll down the list of modules in alphabetical order until you see QgsPoint.

  5. Click on the QgsPoint link to access the label object documentation.

  6. Now go to the PyQGIS API listing at https://github.com/qgis/QGIS/blob/master/python/qsci_apis/PyQGIS-2.2.api.

  7. Scroll down the alphabetical class listing until you see qgis.core.QgsPoint?1().

How it works...

The QGIS API is divided into five distinct categories, as follows:

  • Core

  • GUI

  • Network analysis

  • Server

  • Plugins

Most of the time, it's easy to find the class that targets the functionality you need, with most of QGIS being contained in the catch-all core module. The more you use the API, the quicker you'll be able to locate the objects you need for your scripts. You'll also notice that the API file contains the methods for each class with the type of parameters the class accepts.

There's more...

If you're having trouble locating a class containing the keyword you need, you can use the search engine on the QGIS API website.

Tip

Beware, however, that the results returned by this search engine may contain items you don't need and can even send you in the wrong direction because of the use of similar keywords in different modules.

 

Creating a traditional QGIS plugin


Plugins are the best way to extend QGIS, as they can be easily updated and reused by other people. And as we'll see throughout this book, you can use Python to create plugins. When you create a Python-based plugin, you can usually access that plugin's functionality through the PyQGIS API.

Getting ready

The easiest approach to creating a plugin is to use the Plugin Builder plugin to jump-start development. You can find it in the main QGIS plugin repository and install it.

How to do it...

Perform the following steps to create a simple plugin that displays a dialog box with a custom message:

  1. Start QGIS.

  2. From the Plugins menu, select Plugin Builder and then click on Plugin Builder in the submenu.

  3. In the QGIS Plugin Builder dialog, name the class MyPlugin.

  4. Name the plugin MyPlugin.

  5. Type a short description, such as A demonstration Plugin.

  6. Enter myplugin as the Module name.

  7. Leave the default version numbers as they are.

  8. Enter your name and e-mail address for author information.

  9. Click Next.

  10. Enter a description of the plugin in the About field.

  11. Click Next.

  12. In the Text for menu item field, enter My Plugin.

  13. Click Next and then on the next dialog click Next again.

  14. For the Bug Tracker field, enter https://github.com/GeospatialPython/Learn/issues.

  15. For the Repository field, https://github.com/GeospatialPython/Learn/.

  16. Ensure that the checkbox labeled Flag the plugin as experimental is checked.

  17. Click on the OK button.

  18. A file browser dialog will appear. You can choose a folder in which you want to create your plugin. Select one of the folders called plugins within the python folder in either the main user directory or the QGIS program directory. The following examples are from a Windows machine. You should use the folder in your user directory, which is the preferred place for third-party plugins. QGIS standard plugins go to the main program directory:

      C:\Users\<username>\.qgis2\python\plugins or the %USERPROFILE%
          environment variable
    
    C:\Program Files\QGIS2.18\apps\qgis\python\plugins
    

    On OS X or Linux machines, the .qgis2 directory will be in your home directory.

  19. Close the Plugin Builder information dialog by clicking on the OK button.

  20. Using Command Prompt, navigate to your new plugin template folder.

  21. Use the pyrcc4 command to compile the resource file:

          pyrcc4 -o resources_rc.py resources.qrc
    

    Tip

    If you are on Windows, it is easier to use the OSGEO4W shell, which is installed along with QGIS for the Qt compilation tools to work properly.

  22. In a text editor, such as Windows Notepad or vi on Linux, open the user interface XML file named myplugin_dialog_base.ui.

  23. Insert the following XML for a custom label near line 31, just before the last </widget> tag. Save the file after this edit:

            <widget class="QLabel" name="label"> 
              <property name="geometry"> 
                <rect> 
                  <x>120</x> 
                  <y>80</y> 
                  <width>201</width> 
                  <height>20</height> 
                </rect> 
              </property> 
              <property name="font"> 
                <font> 
                  <pointsize>14</pointsize> 
                </font> 
              </property> 
              <property name="text"> 
                <string>Geospatial Python Rocks!</string> 
              </property> 
            </widget> 
    
  24. Now compile the ui file using the pyuic4 tool:

    pyuic4 -o ui_myplugin.py ui_myplugin.ui
    
  25. Your plugin is now ready. Restart QGIS.

  26. Select My Plugin from the Plugins menu and then select My Plugin from the submenu to see the dialog you created within QGIS, as shown here:

How it works...

This recipe shows you the bare bones needed to make a working plugin. Although we haven't altered it, the code for the plugin's behavior is contained in myplugin.py. You can change the icon and the GUI and just recompile any time you want. Note that we must compile the Qt4 portion of the plugin, which creates the dialog box. The entire QGIS GUI is built on the Qt4 library, so the pyrrc4 compiler and pyuic4 is included to compile the GUI widgets.

You can download the completed plugin with both the source and compiled UI and resource files at https://github.com/GeospatialPython/Learn/raw/master/MyPlugin.zip.

Note

You can find out more about QGIS plugins, including the purpose of the other files in the directory, from the QGIS documentation at http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/plugins.html.

There's more...

We have edited the myplugin_dialog_base.ui XML file manually to make a small change. However, there is a better way to use Qt Creator. Qt Creator is a fully fledged open source GUI designer for the Qt framework. It is an easy what-you-see-is-what-you-get editor for Qt Widgets, including PyQGIS plugins, that uses the included Qt Designer interface. On Windows, Qt Designer can be found in the QGIS program directory within the bin directory. It is named designer.exe. On other platforms, Qt Designer is included as part of the qt4-devel package.

Note

You can also download Qt Creator, which includes Qt Designer, from https://www.qt.io/download/.

When you run the installer, you can uncheck all the installation options, except the Tools category, to install just the IDE.

 

Creating a Processing Toolbox plugin


The QGIS Processing Toolbox provides a powerful set of algorithms for QGIS Python programming, which we'll see throughout this book. You add your own scripts to the toolbox, and with the latest version of QGIS, you can now turn those scripts into plugins. You can install these plugins like any other QGIS plugin using Plugin Manager and then have those scripts appear in Processing Toolbox. This process is significantly easier than writing a traditional plugin from scratch.

Getting ready

First you need a script to package as a plugin. You can package multiple scripts into a single plugin, but to keep things simple, use one. This sample script will save the current map view as an image. Create the script using the following steps:

  1. In Processing Toolbox, expand the Scripts tree.

  2. Double-click on the Create new script tool.

  3. In the script editor, add the following code, specifying an output directory for your map images:

            from qgis.utils import iface 
            import datetime 
            c = iface.mapCanvas() 
            t = '{:%Y%m%d%H%M%S}'.format(datetime.datetime.now()) 
            img_path = '<output directory>/map{}.png' 
            c.saveAsImage(img_path.format(t), None, 'PNG') 
    
  4. Click on the Save As icon to save the image in your scripts directory as MapImage.py.

  5. The script will then appear in the User Scripts tree under Scripts in Processing Toolbox.

  6. Set up a map view and then double-click on the script to verify that an image has been created in the output directory.

How to do it...

Now you are ready to create the plugin from your sample script:

  1. Under the script tools section in Processing Toolbox, double-click on Create script collection plugin.

  2. Fill out the metadata fields in the dialog.

  3. Ensure the MapImage script is checked in the Script selector dialog.

  4. When you navigate to the output folder, create a new folder called MapImage:

  5. Click on the OK button

  6. Navigate to the output folder and verify the plugin files were created.

How it works...

From a functional perspective, all the script does is copy the files to your user scripts directory. But the plugin packaging allows you to distribute your work to other users using the QGIS plugin framework.

There's more...

The Processing Toolbox has a script manager similar to the QGIS plugin manager, in which you can download scripts written by other users for processing, or as examples to write your own scripts. To access this script manager, expand the Scripts menu in the Processing Toolbox, then expand the Tools menu, and finally double-click Get scripts from on-line scripts collection. From there, you can browse a list of downloadable scripts.

 

Distributing a plugin


Distributing a QGIS plugin means placing a collection of files on a server as a ZIP file, with a special configuration file, in order to allow the QGIS plugin manager to locate and install the plugin. The QGIS project has an official repository, but third-party repositories are also permitted. The official repository is very strict regarding how the plugin is uploaded, so, for this recipe, we'll set up a simple third-party repository for a sample plugin and test it with the QGIS plugin manager to avoid polluting the main QGIS repository with a test project. You should note that QGIS is released under the GNU General Public License (GPL), so presumably all other plugins fall under the GPL as well, based on the terms of the license.

Getting ready

In order to complete this recipe, you'll need a sample plugin and a web-accessible directory. You'll also need a ZIP tool, such as the free 7-zip program (http://www.7-zip.org/download.html). Both OSX and Windows can compress and decompress zip files natively. On Linux, you may need to download a ZIP tool from your package manager. You can use the MyPlugin example from the Creating a QGIS plugin recipe as the plugin to distribute. For a web directory, you can use a Google Code repository, GitHub repository, or other online directories you can access. Code repositories work well because they are a good place to store a plugin that you are developing.

How to do it...

In the following steps, we will package our plugin, create a server configuration file for it, and place it on a server to create a QGIS plugin repository:

  1. First, zip up the plugin directory to create a .zip file.

  2. Rename the .zip file to contain the plugin's version number:

    Myplugin.0.1.0.zip
    
  3. Upload this file to a publicly accessible web directory.

  4. Upload the icon.png file from your plugin directory to the web directory.

  5. Next, customize a plugins.xml metadata file for your plugin. Most of the data you need can be found in the metatdata.txt file in your plugin directory. The following example provides some guidance:

            <?xml version = '1.0' encoding = 'UTF-8'?> 
            <?xml-stylesheet type="text/xsl"href="" ?> 
            <plugins> 
              <pyqgis_plugin name="My Plugin" version="0.1.0" plugin_id="227"> 
                <description> 
                  <![CDATA[Demonstration of a QGIS Plugin]]> 
                </description> 
                <about></about> 
                <version>0.1.0</version> 
                <qgis_minimum_version>1.8.0</qgis_minimum_version> 
                <qgis_maximum_version>2.9.9</qgis_maximum_version> 
                <homepage> 
                  <![CDATA[https://github.com/GeospatialPython/Learn]]> 
                </homepage> 
                <file_name>MyPlugin.0.1.0.zip</file_name> 
                <icon>https://github.com/GeospatialPython/
                Learn/raw/master/icon_227.png</icon> 
                <author_name><![CDATA[Joel Lawhead]]></author_name> 
                <download_url>https://github.com/GeospatialPython/
                Learn/raw/master/MyPlugin.0.1.0.zip</download_url> 
                <uploaded_by><![CDATA[jll]]></uploaded_by> 
                <create_date>2016-11-19T15:31:19.824333</create_date> 
                <update_date>2016-11-19T15:31:19.824333</update_date> 
                <experimental>True</experimental> 
                <deprecated>False</deprecated> 
                <tracker> 
                  <![CDATA[https://github.com/GeospatialPython/Learn/issues]]> 
                </tracker> 
                <repository> 
                  <![CDATA[https://github.com/GeospatialPython/Learn/]]> 
                </repository> 
                <tags><![CDATA[development,debugging,tools]]></tags> 
                <downloads>0</downloads> 
                <average_vote>0</average_vote> 
                <rating_votes>0</rating_votes> 
              </pyqgis_plugin> 
            </plugins> 
    
  6. Upload the plugins.xml file to your web directory.

  7. Now start QGIS and launch the plugins manager by going to the Plugins menu and selecting Manage and Install Plugins....

  8. In the Settings tab of the Plugins | Settings dialog, scroll down and click on the Add... button.

  9. Give the plugin a name and then add the complete URL to plugins.xml in the URL field.

  10. Click on the OK button.

  11. To make things easier, disable the other repositories by selecting the repository name, clicking on the Edit button, and unchecking the Enabled checkbox.

  12. Click on the OK button

  13. Click on the Not installed tab.

  14. Your test plugin should be the only plugin listed, so select it from the list.

  15. Click on the Install plugin button in the bottom-right corner of the window.

  16. Click on the Close button.

  17. Go to the Plugins menu and select your plugin to ensure that it works.

How it works...

The QGIS repository concept is simple and effective. The plugins.xml file contains a <download_url> tag that points to a ZIP file plugin on the same server or on a different server. The name attribute of the <pyqgis_plugin> tag is what appears in the QGIS plugin manager.

 

Building a standalone application


QGIS is a complete desktop GIS application. However, with PyQGIS, it can also be a comprehensive geospatial Python library to build standalone applications. In this recipe, we will build a simple standalone script that will create a map with a line on it.

Getting ready

All you need to do to get ready is ensure that you have configured Eclipse and PyDev for PyQGIS development, as described in the Setting up your QGIS IDE recipe of this chapter.

How to do it...

In PyDev, create a new project called MyMap with a Python script called MyMap.py, as follows:

  1. In the Eclipse File menu, select New and then click on PyDev Project.

  2. In the PyDev project's Name field, enter MyMap.

  3. Next, select the Python radio button from the Project Type list.

  4. From the Interpreter pull-down menu, select PyQGIS.

  5. Leave the radio button checked for Add project directory to the PYTHONPATH.

  6. Click on the Finish button.

  7. Now select the project in the PyDev package explorer.

  8. From the File menu, select New and then click on File.

  9. Name the file myMap.py.

  10. Click on the Finish button.

  11. Add the following code to the file that is open in the editor:

            from qgis.core import * 
            from qgis.gui import * 
            from qgis.utils import * 
            from PyQt4.QtCore import * 
            from PyQt4.QtGui import * 
     
            app = QgsApplication([], True) 
            path = "C:/Program Files/QGIS2.18/apps/qgis" 
            app.setPrefixPath(path, True) 
            app.initQgis() 
            canvas = QgsMapCanvas() 
            title = "PyQGIS Standalone Application Example" 
            canvas.setWindowTitle(title) 
            canvas.setCanvasColor(Qt.white) 
            layer_info = 'LineString?crs=epsg:4326' 
            layer =  QgsVectorLayer(layer_info, 'MyLine' , "memory") 
            pr = layer.dataProvider() 
            linstr = QgsFeature() 
            wkt = "LINESTRING (1 1, 10 15, 40 35)" 
            geom = QgsGeometry.fromWkt(wkt) 
            linstr.setGeometry(geom) 
            pr.addFeatures([linstr]) 
            layer.updateExtents() 
            QgsMapLayerRegistry.instance().addMapLayer(layer) 
            canvas.setExtent(layer.extent()) 
            canvas.setLayerSet([QgsMapCanvasLayer(layer)]) 
            canvas.zoomToFullExtent() 
            canvas.show() 
            exitcode = app.exec_() 
            QgsApplication.exitQgis() 
            sys.exit(exitcode) 
    
  12. From the Run menu, select Run.

  13. Verify that the standalone QGIS map appears in a new window, as shown here:

How it works...

This recipe uses as little code as possible to create a map canvas and draw a line to demonstrate the skeleton of a standalone application, which you can build up further to add more functionality, as we will see in later recipes.

To create line geometry, we use Well-Known Text (WKT), which provides a simple way to define the line vertices without creating a bunch of objects. The map does not appear until you call the canvas.show() method. This allows you to set up the map behind the scenes and then display it when it is complete.

There's more...

The standalone application can be compiled into an executable that can be distributed without installing QGIS using either py2exe or PyInstaller.

You can find out more about py2exe at http://www.py2exe.org.

You can learn more about PyInstaller at https://github.com/pyinstaller/pyinstaller/wiki.

 

Storing and reading global preferences


PyQGIS allows you to store application-level preferences and retrieve them. QGIS also has project-level preferences, which can override the application-level preferences in some cases. In this recipe, we'll focus on reading and writing the global preferences that serve as the application defaults. QGIS actually takes advantage of Qt's built-in preferences management.

Getting ready

This code can be run in any type of PyQGIS application. In this example, we'll run it in the QGIS Python console for an easy demonstration. We'll also change the default CRS for new projects and then read the value back from the global settings.

How to do it...

In this recipe, we will set the default projection used by QGIS for new projects. We'll do this using the Python console:

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. We will need to import the Qt core library, as follows:

            from PyQt4.QtCore import * 
    
  4. In the Python console, run the following code:

            settings = QSettings(QSettings.NativeFormat,
                                 QSettings.UserScope,'QuantumGIS', 'QGis') 
            settings.setValue('/Projections/projectDefaultCrs', 'EPSG:2278') 
            settings.value('/Projections/projectDefaultCrs') 
            settings.sync() 
    

How it works...

This API is actually the Qt API that QGIS relies on for settings. In the QSettings object, we specify the native format for storage, which is the default format for the platform. On Windows, the format is the registry; on OS X, it's the plist files, and on Unix, it's the text files. The other QSettings parameters are the organization and the application, often used as a hierarchy to store information. Note that when you change the settings, you must call the sync() method at the end to save them and let them take effect. Note that when you are writing a standalone QGIS application, you should use your own organization and application name for settings and not QGIS.

There's more...

If you want to see all the options that you can change, call the allKeys() method of QSettings; this will return a list of all the setting names.

 

Storing and reading project preferences


The QGIS application settings are stored using the Qt API. However, QGIS project settings have their own object. In this recipe, we'll set and read the project title, and then set and read a custom preference for a plugin.

Getting ready

We are going to set a plugin preference using the sample plugin created in an earlier recipe, Creating a QGIS plugin, of this chapter. You can substitute the name of any plugin you want, however. We will also run this recipe in the QGIS Python console for quick testing, but this code will normally be used in a plugin.

How to do it...

In this recipe, we will first write and then read the title of the current project. Then, we will create a custom value for a plugin called splash, which can be used for the plugin startup splash screen if desired. Here are the steps to store and read project preferences:

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. In the console, run the following code:

            proj = QgsProject.instance() 
            proj.title("My QGIS Project") 
            proj.title() 
            msg = "Geospatial Python Rocks!" 
            proj.writeEntry("MyPlugin", "splash", msg) 
            proj.readEntry("MyPlugin", "splash", "Welcome!")[0] 
    

How it works...

In the first two lines, we change the title of the current active project and then echo it back. In the next set of two lines, we set up and read the custom settings for a plugin. Notice that the readEntry() method returns a tuple with the desired text and a boolean, acknowledging that the value is set, so we extract the first index to get the text. The read method also allows the default text in case that property is not set (rather than throw an exception, which must be handled), as well as the boolean value False to inform you that the default text was used because the property was not set. The values you set using this method are stored in the project's XML file when you save it.

There's more...

The Qgs Project object has a number of methods and properties that may be useful. The QGIS API documentation details all of them at http://qgis.org/api/classQgsProject.html.

 

Accessing the script path from within your script


Sometimes, you need to know exactly where the current working directory is so that you can access external resources.

Getting ready

This code uses the Python built-in library, and can be used in any context. We will run this recipe in the QGIS Python console.

How to do it...

In this recipe, we will get the current working directory of the Python console, which can change with the configuration:

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. In the Python console, run the following code:

            import os 
            os.getcwd() 
    

How it works...

QGIS relies heavily on file system paths to run the application and manage external data. When writing cross-platform QGIS code, you cannot assume the working directory of your script.

There's more...

You can also use Python's __file__ variable, which tells you the path of the script currently being executed. For example, path = os.path.dirname(__file__)

On his blog, one of the QGIS developers, Gary Sherman, has an excellent post about the various aspects of path variables in QGIS beyond just the execution directory. You can check it out at http://spatialgalaxy.net/2013/11/06/getting-paths-with-pyqgis/.

About the Author
  • Joel Lawhead

    Joel Lawhead is a PMI-certified Project Management Professional (PMP), a certified GIS Professional (GISP), and vice president of NVision Solutions, Inc., an award-winning firm specializing in geospatial technology integration and sensor engineering for NASA, FEMA, NOAA, the US Navy, and many other commercial and non-profit organizations. Joel began using Python in 1997 and started combining it with geospatial software development in 2000. He has authored multiple editions of Learning Geospatial Analysis with Python and QGIS Python Programming Cookbook, both from Packt. He is also the developer of the open source Python Shapefile Library (PyShp) and maintains a geospatial technical blog.

    Browse publications by this author
Latest Reviews (5 reviews total)
Very, very interesting topics.
Prima boeken. De opzet en layout lijkt overdreven simpel maar blijkt erg goed om je snel op de goede weg te helpen.
Tens of very useful recipes for QGIS and Python. ;-)
QGIS Python Programming Cookbook, Second Edition - Second Edition
Unlock this book and the full library FREE for 7 days
Start now