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
PolyGeo
65.5k29 gold badges115 silver badges349 bronze badges
asked Dec 28, 2013 at 21:24
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. 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

PolyGeo
65.5k29 gold badges115 silver badges349 bronze badges
answered Dec 29, 2013 at 19:15
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. 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() 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) 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(...)
answered Jan 3, 2014 at 23:18

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.