6

I'm writing a Python script to use it in Processing framework. I need to cancel script execution if certain conditions are met (to save user's time). I tried to use sys.exit(arguments) command. The issue is that not only the script, but QGIS itself shuts down too. I also tried quit() but result is the same. How should I terminate script in Processing framework?

The following code is for reproduction purpose only. I don't need ad hoc solution for this particular case because I already have it. I need to know how to deal with this issue in general.

##Raster processing=group
##raster_1=raster
##raster_2=raster


from osgeo import gdal
import sys
from numpy import *
import ntpath
import re
import platform
from PyQt4 import QtGui


raster_1 = gdal.Open(raster_1)
raster_2 = gdal.Open(raster_2)

rasters_list = [raster_1, raster_2]

# create a message for the case when CRSs of rasters do not match
class WrongCRS(QtGui.QMessageBox):

  def __init__(self):
    super(WrongCRS, self).__init__()

    self.initUI()

  def initUI(self):

    self.warning(self, 'Oops!',
            "Rasters must have the same CRS!\n\nExecution cancelled!", QtGui.QMessageBox.Ok)

# check CRS
proj = None
for raster in rasters_list:
  new_proj = raster.GetProjection()
  if proj is None:
    proj = new_proj
  else:
    if proj != new_proj:
      WrongCRS()
      sys.exit('CRSs do not match!')
    else:
      continue
2
  • it might be helpful to get to know a bit more about your code(not only for reproduction). Are you trying to interrupt within a forloop or a try-catch phrase? I often end my script with writing none into all open files/variables.
    – Curlew
    Commented Dec 29, 2013 at 0:56
  • @Curlew, I added relevant part of code. Commented Dec 29, 2013 at 11:59

2 Answers 2

6
  • first thing, osgeo.gdal is for pure Python scripting:

    from osgeo import gdal  
    raster  = gdal.Open('your.tif')   
    raster.GetProjection()
    

Everything else is a problem of osgeo, and not of PyQGIS, since you use 2 QGIS existing layers:

 ##raster_1=raster  
 ##raster_2=raster

you don't need it. To process the layers, the correct code is:

raster_1 = processing.getobject(raster_1)   
raster_2 = processing.getobject(raster_2)

an the crs is given by:

new_proj = raster.crs()
  • second thing, you cannot load a raster in QGIS without projection (if not yet existing, it is chosen by QGIS, according to some criteria):

enter image description here

So your first condition if proj is None:, is unnecessary and your script become (you don't need a list with only two layers):

raster_1 = processing.getobject(raster_1)
raster_2 = processing.getobject(raster_2)
if raster_1.crs()==raster_2.crs():
     action
else:
     WrongCRS()

and the script terminate by himself.


in the last version of the processing module, it is now:

processing.getObjects()

For terminate the script, you can embed your script in a function and use sys.exitfunc() (I use the Python console to to see the results)

example:

import atexit
.....
def all_done():
    message = '- Rasters must have the same CRS!\n\nExecution cancelled!'
    print message   
atexit.register(all_done)
raster_1 = processing.getObject(raster_1)
raster_2 = processing.getObject(raster_2)
def main():
    if raster_1.crs() != raster_2.crs():
         sys.exitfunc()
    else:
          message = "ok"
          print message
          continue
main()

Result in the Python console:

enter image description here

6
  • FYI processing.getobjects() doesn't work any more. Thank you for advices on my code improvements, but I didn't ask for it and frankly they are pointless, cause I didn't ask for them and I had my reasons for that structure.Have you actually tested your own solution? After else: WrongCRS there are lines of code in my script and they will be executed if the script is not terminated. Finally where is the answer for my question that I expressed quite clear: how to terminate script in processing framework in general?. I was very close to down-vote your answer. Commented Dec 29, 2013 at 20:20
  • 1
    If you use the last version of processing, it is now processing.getObjects() (look at Create_tiling_from_vector_layer.py) but down-vote if you want.
    – gene
    Commented Dec 29, 2013 at 20:45
  • ok, good to know. BTW it was't me who down-voted your answer. Commented Dec 29, 2013 at 21:20
  • 1
    It is a problem of PyQT4, look at simple IPython example raises exception on sys.exit()
    – gene
    Commented Dec 29, 2013 at 21:38
  • 1
    sys.exit()kills Python and QGIS. I found another solution: embedding the code in a function and using sys.exitfunc()(see above)
    – gene
    Commented Dec 29, 2013 at 23:08
5

It is impossible (for now at least) to terminate Processing python script and leave QGIS itself untouched. It was suggested by @gene to use sys.exitfunc() to terminate main function. However I find it more useful to use just return message to just end function normally. Here is pseudo code:

class ErrorMessage(...):
  .....

def checkFunction(parameter):
  if parameter == condition:
    return False
  else:
    return True

def jobFunction(...):
  ...
  if parameter_1 == condition_1:
    return False

  result = ...
  return result

def main(...):
  if not checkFunction(parameter):
    return ErrorMessage(...)

  result = jobFunction(...)
  if result == False:
    return ErrorMessage(...)

  return result

main(...)

Your Answer

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

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