11

I've tried going through IRC to see if people can help me out with this, but the medium seems a little clumsy for making any answers clear, so I'm going to try this instead.

I would like to program a standalone application using PyQGIS the way I can already program standalone applications using ArcPy.

PyQGIS itself is straightforward. I have had no difficulty using running Python scripts within the QGIS console editor. However, in order to use the Python bindings in a standalone script, I am advised I must change the environment settings using a batch script (I'm using Windows Vista at home, so we're talking batch scripting for Windows). This has resulted in a mess on my end, as I don't really understand batch scripting, and I don't like the idea that I'm resetting an environment that needs to be a certain way for other applications I run.

I'm having difficulty understanding why the instructions for creating these settings are so unnecessarily complicated, and why they don't amount to one line of code saying "go to where the bindings are, make the libraries I want available for this program to use). Certainly ArcPy doesn't require people to mess around with the computer's environmental settings, so I'm having difficulty understanding why PyQGIS does. It seems to me people will simply give up rather than teach themselves Windows Batch Scripting Language.

Now, I notice that when I run a script in QGIS's console editor, it works. Granted, it also makes the rest of QGIS unusable after the script runs, so I have to restart QGIS again afterwards, but the script works exactly as I programmed it to work. But when I do so outside of the QGIS application, it does not. The issue does not appear to be that I have failed to import some Python package automatically imported by the QGIS application (qgis.core and qgis.utils) - I have those import statements in my standalone script, along with all the other package imports the script requires. This leads me to believe that the difference is that the QGIS application correctly sets external environment variables, but those variables are not set properly when I run it as a standalone script.

Additionally, when I run the script as a standalone script, it gets through all of the code without throwing an error; it simply does not do what the code commands. When I run the script in the console editor, it does it all correctly. When I run it as a standalone, it creates a window, then immediately destroys it, while throwing no errors. So the intepreter understands everything I'm asking the script to do - it just won't do it.

Here is the script:

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

qgishome = "c:/OSGeo4W/apps/qgis/"
app = QgsApplication([], True)
QgsApplication.setPrefixPath(qgishome, True)
QgsApplication.initQgis()

canvas = QgsMapCanvas()
canvas.setCanvasColor(Qt.yellow)
canvas.enableAntiAliasing(True)
canvas.show()

layer = QgsVectorLayer(r"c:/GIS Data/fed308/cpc.shp", "Ridings", "ogr")
reg = QgsMapLayerRegistry.instance()
reg.addMapLayer(layer)
canvas.setExtent(layer.extent())
canvas.setLayerSet([QgsMapCanvasLayer(layer)])
QgsApplication.exitQgis()

Please...is there some way I can run this script outside of QGIS and have it work as it does within QGIS (ideally without shutting things down at the very end)?

QGIS is a wonderful program, and PyQGIS seems as intuitive as ArcPy does and would be a real advantage for an open source software to have - but if people have to go through all the hoops I have gone through already, and still not have standalone application access to PyQGIS libraries the way they do have access to ArcPy, it seems to me PyQGIS won't be of much use to people. I hope I'm wrong and this is easier than it thus far has been. Does anyone have a solution?

6

You have to start the Qt event loop using:

app.exec_()

I would remove QgsApplication.exitQgis(). It should ideally be handled in a slot that is connected to lastWindowClosed() signal of the application.

  • Good to know. I will direct my energies to reading up on PyQt4 so I know more what I need to do to make any GUIs I attempt in the future work. If G. Sherman of the Script Runner plugin fame...I noticed when I was attempting to run this code without any of the references to QgsApplication, and with the def run_script header Script Runner needs, my script did exactly what it was doing when I was trying the script as shown above as a standalone script...creating a window and then immediately closing it. This was part of why I assumed I was having continuing environmental variables problems. – Zak Klaas Nov 16 '13 at 0:21
7

Consulting the PyQGis documentation, you’ll find that there are four main ways to utilize the PyQGis API:

  1. via commands in the Python console
  2. via Python scripts in Processing or with the ScritRunner plugin of Gary Sherman
  3. via development of custom plugins to the QGis application
  4. outside QGIS (in the Python shell or creating an applications with PyQt4 and not Tkinter (why import Tkinter twice ?)

and you are interested in this last point:

  • you can use PyQGIS as any other Python module. But Python does not know where to find PyQGIS. For that, you need to add the PyQGIS folder to the PYTHONPATH (for Windows, look at How to add to the pythonpath in windows 7?).

Certainly ArcPy doesn't require people to mess around with the computer's environmental settings, so I'm having difficulty understanding why PyQGIS does

Because you use the Python version of ArcGIS, in other cases, the same is true, look using arcpy outside arcmap or Configure PyScripter to use with QGIS (and still use arcpy) on Windows, for example.

You don't need here PyQt4, Tkinter or qgis.gui:

from qgis.core import *
QgsApplication.setPrefixPath("yourpath", True)
QgsApplication.initQgis()
# or your solution
# read a shapefile 
layer = QgsVectorLayer('your.shp', 'your', 'ogr')
layer.isValid()
True
# loop through layer 
for elem in layer.getFeatures():
    geom= elem.geometry()
    attr =elem.attributes()
    (processing)

 # interaction with other Python module: Shapely, for example
 from shapely.geometry import shape
 from json import loads
 for elem in layer.getFeatures():
       shapely_geometry = shape(loads(elem.geometry().exportToGeoJSON()))
  • you can create an application. You need here PyQt4 (and not Tkinter) and qgis.gui.

I would like to program a standalone application using PyQGIS the way I can already program standalone applications using ArcPy.

So, for that, you must learn PyQt4 , as you have to learn Tkinter (or wxPython), for example. This is another problem: the solution given by gsherman is a problem of PyQt4, not of PyQGIS (look at PyQt4 tutorial, for example)

  • Thanks. I hadn't yet heard anyone describe PyQt4 as something that was a sort of exclusive alternative to Tkinter, which I know pretty well now (not sure why I declared it twice in the above code...that was just a mistake). Your link to the PyQt4 tutorial seems like it will be very helpful. After experimenting today, I elected to solve my problem by means of the console editor and having the script minimise the window of the QGIS GUI so my script's window appears to be a standalone, with QGIS running in the background - so I guess that's number 1 in your list of 4 possibilities. – Zak Klaas Nov 16 '13 at 0:14

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.