The QGIS Python console is great for doing one-off tasks or experimenting with the API. Sometimes you might want to automate a task using a script, and do it without writing a full blown plugin. Currently QGIS does not have a way to load an arbitrary Python script and run it. Until it does, this post illustrates a way you can create a script and run it from the console.
There are a couple of requirements to run a script in the console:
The script must be in your PYTHONPATH
Just like a QGIS plugin, the script needs a reference to qgis.utils.iface
Setting up the Environment
By default, the Python path includes the .qgis/python directory. The location depends on your platform:
Windows: in your home directory under .qgis\python. For example, C:\Documents and Settings\gsherman.qgis\python
Linux and OS X: $HOME/.qgis/python
To see what is in your PYTHONPATH you can do the following in QGIS Python console:
import sys sys.path
While you could use the .qgis\python directory for your custom scripts, a better way is to create a directory specifically for that purpose and add that directory to the PYTHONPATH environment variable. On Windows you can do this using the Environment Variables page in your system properties:
On Linux or OS X, you can add it to your .bash_profile, .profile, or other login script in your home directory:
Writing the Script
With the environment set, we can create scripts to automate QGIS tasks and run them from the console. For this example, we will use a simple script to load all shapefiles in a specified directory. There are a couple of ways to do this:
Write a simple script with a function that accepts qgis.utils.iface as an argument, along with a path to the shapefiles
Create a Python class that uses an init method to store a reference to the iface object and then add methods to do the work
We will use the latter approach because it is more flexible and allows us to initialize once and then call methods without having to pass the iface object each time.
The script looks like this:
#!/usr/bin/env Python """Load all shapefiles in a given directory. This script (loader.py) runs from the QGIS Python console. From the console, use: from loader import Loader ldr = Loader(qgis.utils.iface) ldr.load_shapefiles('/my/path/to/shapefile/directory') """ from glob import glob from os import path class Loader: def __init__(self, iface): """Initialize using the qgis.utils.iface object passed from the console. """ self.iface = iface def load_shapefiles(self, shp_path): """Load all shapefiles found in shp_path""" print "Loading shapes from %s" % path.join(shp_path, "*.shp") shps = glob(path.join(shp_path, "*.shp")) for shp in shps: (shpdir, shpfile) = path.split(shp) self.iface.addVectorLayer(shp, shpfile, 'ogr' )
Running the Script
To open the console use the Plugins->Python Console menu item.
The comment at the head of the script explains how to use it.
First we import the Loader class from the script file (named loader.py). This script resides in the qgis_scripts directory that is our PYTHONPATH.
from loader import Loader
We then create an instance of Loader, passing it the reference to the iface object:
ldr = Loader(qgis.utils.iface)
This creates the Loader object and calls the init method to initialize things.
Once we have an instance of Loader we can load all the shapefiles in a directory by calling the loadshapefiles_ method, passing it the full path to the directory containing the shapefiles:
The loadshapefiles_ method uses the path to get a list of all the shapefiles and then adds them to QGIS using addVectorLayer.
Here is the result, rendered in the random colors and order that the shapefiles were loaded:
When testing a script in the console you may need to reload it as you make changes. This can be done using reload and the name of the module. In our example, reload(loader) does the trick.
You can add more methods to your class to do additional tasks
You can create a "driver" script that accepts the iface object and then initializes additional classes to do more complex tasks
. I have plans on the drawing board to implement this feature.