3

I have a script that creates a multi-distance buffer rings and have managed to migrate it successfully to QGIS 3.4.5. This script requires me to select a layer, and a feature in the layer before I run it, as such:

from math import *
from qgis.core import *
from qgis.utils import iface
from PyQt5.QtCore import *
geom = iface.activeLayer().selectedFeatures()[0].geometry()
start_x = geom.asPoint().x()
start_y = geom.asPoint().y()
sides = 64
radius = 6378137.0 # meters
# create layer
vl = QgsVectorLayer("Polygon", "Distance Buffers", "memory")
pr = vl.dataProvider()
# changes are only possible when editing the layer
vl.startEditing()
# add fields
pr.addAttributes([QgsField("Distance", QVariant.Int), QgsField("Label", QVariant.String)])
distance = [250, 500, 1000, 2000, 3000, 4000, 5000, 10000, 15000, 20000, 25000, 30000, 40000, 50000]
for i in range(len(distance)):
 points = []
 dist = distance[i]
 degrees = 0
 while degrees <= 360:
 degrees = degrees + 360 / sides
 start_lon = start_x * pi / 180
 start_lat = start_y * pi / 180
 bearing = degrees * pi / 180
 end_lat = asin((sin(start_lat) * cos(dist / radius)) + (cos(start_lat) * sin(dist / radius) * cos(bearing)))
 end_lon = start_lon + atan2(sin(bearing) * sin(dist / radius) * cos(start_lat),
 cos(dist / radius) - (sin(start_lat) * sin(end_lat)))
 points.append(QgsPointXY(end_lon * 180 / pi, end_lat * 180 / pi))
 fet_name = str(distance[i])
 if distance[i] < 1000:
 label = str(distance[i]) + "m"
 else:
 label = str(distance[i]/1000) + "km"
 # add a feature
 fet = QgsFeature()
 geometry = QgsGeometry.fromPolygonXY([points])
 fet.setGeometry(geometry)
 fet.setAttributes([fet_name,label])
 pr.addFeatures([fet])
# commit to stop editing the layer
vl.commitChanges()
# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.updateExtents()
myDir = QgsProject.instance().readPath("./")
file_name = 'Distance Buffers' + '.shp'
ShapefileDir = myDir + "/Shapefiles/" + file_name
_writer = QgsVectorFileWriter.writeAsVectorFormat(vl, ShapefileDir, "utf-8", driverName="ESRI Shapefile")
# add layer to the legend
name = 'Distance Buffers'
BufferShp = QgsVectorLayer(ShapefileDir,name, 'ogr')
QgsProject.instance().addMapLayer(BufferShp)
# change active layer
lyr = QgsProject.instance().mapLayersByName(name)[0]
iface.setActiveLayer(lyr)
buffer_lyr = iface.activeLayer()
# load preset qgis style file
buffer_lyr.loadNamedStyle("W:/2. SGER-Economics/c. Project Resources/8. GIS/QGIS Style File/Buffer.qml")
buffer_lyr.triggerRepaint()

I have noticed a few strange behaviors:

  1. When I 'Add Script to Toolbox', it immediately tries to run the script, rather than just updating the toolbox to include the selected script.

  2. After I run it successfully for the first time, I see that the script is now added to my toolbox. However, when I try to run it again, nothing happens. To run it I have to manually open the script in the Processing Script Editor, then Run Script.

  3. After the script is added, whenever I start a new instance of QGIS, I get an error message as such:

An error has occurred while executing Python code:

AttributeError: 'NoneType' object has no attribute 'selectedFeatures' Traceback (most recent call last): File "C:/PROGRA~1/QGIS3~1.4/apps/qgis-ltr/./python/plugins\processing\script\ScriptAlgorithmProvider.py", line 111, in loadAlgorithms alg = ScriptUtils.loadAlgorithm(moduleName, filePath) File "C:/PROGRA~1/QGIS3~1.4/apps/qgis-ltr/./python/plugins\processing\script\ScriptUtils.py", line 68, in loadAlgorithm spec.loader.exec_module(module) File "", line 728, in exec_module File "", line 219, in _call_with_frames_removed File "\file05\Production2円. SGER-Economics\c. Project Resources8円. GIS\QGIS Processing Scripts\Buffer_QGIS3.py", line 6, in geom = iface.activeLayer().selectedFeatures()[0].geometry() AttributeError: 'NoneType' object has no attribute 'selectedFeatures'

I assume all of this happens because for some reason QGIS is trying to run my script on its own whenever it opens. Is there something wrong with my script or is this a bug with the new QGIS?

asked Feb 27, 2019 at 2:02
0

1 Answer 1

5

There is a fairly rigid structure for creating a processing script for the QGIS processing tool box, the basis of which is sub-classing and creating an instance of the QgsProcessingAlgorithm class.

In addition to the QGIS3 processing script template by @underdark, there is an excellent tutorial by @spatialthoughts, "Writing Python Scripts for Processing Framework", which has recently been updated for QGIS3.

user2856
73.7k7 gold badges123 silver badges207 bronze badges
answered Feb 27, 2019 at 3:36

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.