使用QGIS 3.0编写python处理脚本


17

在对QGIS 3.0进行更新之后,很难找到有关在QGIS 3.0中编写处理脚本的任何信息。

@Underdark(请参阅此处)为框架提供了基础。从模板(QGIS 3.0.2)编写新脚本时,似乎也已在QGIS中添加了此代码。

但是,我找不到任何方法来帮助像我这样的Python新手了解如何更改该代码,尤其是对于输入和输出层。

我的目标是编写一个脚本,该脚本以2个栅格图层和一个double图层作为输入,输出两个图层。

允许对示例代码进行哪些更改?

对于QGIS 2.x,我将使用以下语法:

##Layer1=raster
##Layer2=raster 
##myDouble=Double
##OutLayer1=output raster
##OutLayer2=output raster   

据我了解,必须在以下过程中进行更改,但是我不确定要执行的操作。

def initAlgorithm(self, config=None):
    self.addParameter(QgsProcessingParameterFeatureSource(
        self.INPUT,
        self.tr("Input layer"),
        [QgsProcessing.TypeVectorAnyGeometry]))
    self.addParameter(QgsProcessingParameterFeatureSink(
        self.OUTPUT,
        self.tr("Output layer"),
        QgsProcessing.TypeVectorAnyGeometry))

5月16日,发布了QGIS Python API文档。但是,我仍然不清楚如何在这里使用它。(这很可能是缺乏Python知识)


1
您能否提供在qgis 2.xx上用于相同目的的代码示例,qgis 3.x上的文档将在此处提供:docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/…将尽快提供。更新。在此跟踪文档问题:github.com/qgis/QGIS-Documentation/issues
Nono,

用代码示例编辑的答案。感谢您提供的链接,我已经在阅读食谱,但是很遗憾,我在这里找不到答案!
坎丹

我阅读了有关Qgis API文档的信息,但我无法将其与@Underdark的代码联系起来。(请参见链接的编辑)
Kantan

Answers:


29

随着从QGIS2.x到QGIS3.x的过渡,整个处理框架都进行了重新设计,其中很大一部分现在都可以作为C ++类运行,您可以使用Python与之交互。不幸的是,用于数据/数据集IO的简单参数语法不再有效。在您预安装在工具箱中的内置(Python-)处理算法之后,新的参数结构更具针对性。

如我所见,您已经按照@underdark对新算法结构进行了描述。但是,为了根据您的要求(栅格图层,双重输入等)调整此结构,您必须在脚本中的多个位置更改代码。我已经为您编写了一个带有简短说明的粗略示例(只是基于@underdarks示例的算法框架):

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsProcessing, QgsProcessingAlgorithm, 
QgsProcessingParameterRasterLayer,QgsProcessingParameterNumber, 
QgsProcessingParameterRasterDestination)

class RasterAlg(QgsProcessingAlgorithm):
    INPUT_RASTER_A = 'INPUT_RASTER_A'
    INPUT_RASTER_B = 'INPUT_RASTER_B'
    INPUT_DOUBLE = 'INPUT_DOUBLE'
    OUTPUT_RASTER_A = 'OUTPUT_RASTER_A'
    OUTPUT_RASTER_B = 'OUTPUT_RASTER_B'

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

    def name(self):
        return "RasterAlg"

    def tr(self, text):
        return QCoreApplication.translate("RasterAlg", text)

    def displayName(self):
        return self.tr("RasterAlg script")

    def group(self):
        return self.tr("RasterAlgs")

    def groupId(self):
        return "RasterAlgs"

    def shortHelpString(self):
        return self.tr("RasterAlg script without logic")

    def helpUrl(self):
        return "https://qgis.org"

    def createInstance(self):
        return type(self)()

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterRasterLayer(
            self.INPUT_RASTER_A,
            self.tr("Input Raster A"), None, False))
        self.addParameter(QgsProcessingParameterRasterLayer(
            self.INPUT_RASTER_B,
            self.tr("Input Raster B"), None, False))
        self.addParameter(QgsProcessingParameterNumber(
            self.INPUT_DOUBLE, 
            self.tr("Input Double"), 
            QgsProcessingParameterNumber.Double,
            QVariant(1.0)))
        self.addParameter(QgsProcessingParameterRasterDestination(
            self.OUTPUT_RASTER_A,
            self.tr("Output Raster A"),
            None, False))
        self.addParameter(QgsProcessingParameterRasterDestination(
            self.OUTPUT_RASTER_B,
            self.tr("Output Raster B"),
            None, False))

    def processAlgorithm(self, parameters, context, feedback):
        raster_a = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER_A, context)
        raster_b = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER_B, context)
        double_val = self.parameterAsDouble(parameters, self.INPUT_DOUBLE,context)
        output_path_raster_a = self.parameterAsOutputLayer(parameters, self.OUTPUT_RASTER_A, context)
        output_path_raster_b = self.parameterAsOutputLayer(parameters, self.OUTPUT_RASTER_B, context)

        #DO SOME CALCULATION

        results = {}
        results[self.OUTPUT_RASTER_A] = output_path_raster_a
        results[self.OUTPUT_RASTER_B] = output_path_raster_b
        return results

完成哪些步骤?

  1. 导入所有必要的类。
  2. 将算法定义为继承自的类QgsProcessingAlgorithm
  3. 首先,您必须将输入和输出参数的名称声明为算法类(即)的字符串变量(参数名称),INPUT_RASTER_A = 'INPUT_RASTER_A'以便使用处理框架提供的参数引用算法。
  4. 添加将算法连接到处理工具箱gui并提供帮助字符串等的方法。
  5. 然后,添加处理框架的参数。对于QgsProcessingParameterType您的算法QgsProcessingParameterRasterLayer,这些定义为-的子类:,QgsProcessingParameterNumber等等。您可以查阅API条目(即QgsProcessingParameterRasterLayer),以传递正确的参数并构造参数对象。
  6. 将参数旁边的contextfeedback对象传递到processAlgorithm()方法中,在该方法中您可以在运行时从参数中获取输入数据集(在这种情况下,通过使用parameterAsRasterLayer()方法等,可以使用QgsRasterLayer对象)。
  7. 做你的计算。
  8. 将输出添加到结果字典中,并作为调用的结果返回processAlgorithm()

希望我能给您一些有关如何在QGIS3中设计python算法的见解。无论何时遇到困难,查看处理框架的现有算法如何处理参数总是有帮助的。你可以在这里看看他们。


1
写得好!介意我将其添加到github.com/qgis/QGIS/blob/master/doc/porting_processing.dox吗?
恩道森

如果您将其添加到qgis文档中,将不胜感激。请这样做!是否有为qgis3贡献更多python文档的前提条件?我认为这对于扩大脚本作者和程序员的用户群至关重要。
root676

1
没有先决条件。实际上,通过GitHub拉取请求添加到官方python食谱中非常容易(所有编辑甚至都可以在GitHub站点上完成:github.com/qgis/QGIS-Documentation/tree/master/source/docs/…)。非常欢迎在官方文档中添加更多示例!
恩道森

1
感谢您的回答!我今天很忙,但明天我会尝试挖掘。看起来真的很有希望。
坎丹'18

2
这绝对是一个不错的答案,感谢您的详细信息和参考。gitHub上脚本的链接是一个真正的金矿!最初,QVariant声明给了我一个错误,但是当我在编辑器中重新键入它并使用自动完成功能时,该错误消失了。现在,真正需要深入研究脚本,我希望它不会阻止新程序员。但是,随着越来越多的文档可用,我希望它变得更加清晰!
坎丹
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.