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 Answers 2
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
-
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? Afterelse: 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.SS_Rebelious– SS_Rebelious2013年12月29日 20:20:56 +00:00Commented Dec 29, 2013 at 20:20 -
1If 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– gene2013年12月29日 20:45:02 +00:00Commented Dec 29, 2013 at 20:45 -
ok, good to know. BTW it was't me who down-voted your answer.SS_Rebelious– SS_Rebelious2013年12月29日 21:20:39 +00:00Commented Dec 29, 2013 at 21:20
-
1It is a problem of PyQT4, look at simple IPython example raises exception on sys.exit()gene– gene2013年12月29日 21:38:36 +00:00Commented Dec 29, 2013 at 21:38
-
1
sys.exit()
kills Python and QGIS. I found another solution: embedding the code in a function and usingsys.exitfunc()
(see above)gene– gene2013年12月29日 23:08:07 +00:00Commented Dec 29, 2013 at 23:08
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(...)
for
loop or atry-catch
phrase? I often end my script with writingnone
into all open files/variables.