26.7. 从控制台使用处理算法

该控制台允许高级用户提高他们的工作效率,并执行无法使用处理框架的任何其他图形用户界面元素执行的复杂操作。可以使用命令行界面定义涉及多种算法的模型,还可以添加其他操作,如循环和条件语句,以创建更灵活、更强大的工作流。

QGIS中没有处理控制台,但所有处理命令都可以从QGIS内置中获取 Python console 。这意味着您可以将这些命令合并到您的控制台工作中,并将处理算法连接到从那里可用的所有其他功能(包括来自QGISAPI的方法)。

您可以从Python控制台执行的代码,即使它不调用任何特定的处理方法,也可以转换为新的算法,稍后可以从工具箱、图形建模器或任何其他组件调用,就像您处理任何其他算法一样。事实上,您可以在工具箱中找到的一些算法是简单的脚本。

在这一节中,我们将了解如何使用QGIS Python控制台中的处理算法,以及如何使用Python编写算法。

26.7.1. 从Python控制台调用算法

您必须做的第一件事是使用以下行导入处理函数:

>>> from qgis import processing

现在,基本上只有一件(有趣的)事情可以从控制台中完成:执行一个算法。这是通过使用 run() 方法,该方法将要执行的算法的名称作为其第一个参数,然后根据算法的要求提供数量可变的附加参数。因此,您首先需要知道的是要执行的算法的名称。这不是您在工具箱中看到的名称,而是唯一的命令行名称。若要为您的算法找到正确的名称,可以使用 processingRegistry 。在您的控制台中键入以下行:

>>> for alg in QgsApplication.processingRegistry().algorithms():
        print(alg.id(), "->", alg.displayName())

您将看到类似这样的内容(添加了一些额外的破折号以提高可读性)。

3d:tessellate --------------> Tessellate
gdal:aspect ----------------> Aspect
gdal:assignprojection ------> Assign projection
gdal:buffervectors ---------> Buffer vectors
gdal:buildvirtualraster ----> Build Virtual Raster
gdal:cliprasterbyextent ----> Clip raster by extent
gdal:cliprasterbymasklayer -> Clip raster by mask layer
gdal:clipvectorbyextent ----> Clip vector by extent
gdal:clipvectorbypolygon ---> Clip vector by mask layer
gdal:colorrelief -----------> Color relief
gdal:contour ---------------> Contour
gdal:convertformat ---------> Convert format
gdal:dissolve --------------> Dissolve
...

这是所有可用的算法ID的列表,按提供程序名称和算法名称排序,以及它们的对应名称。

一旦知道了算法的命令行名,接下来要做的就是确定正确的语法来执行它。这意味着在调用 run() 方法。

有一种方法可以详细描述算法,该方法可用于获取算法所需的参数及其将生成的输出的列表。要获取此信息,您可以使用 algorithmHelp(id_of_the_algorithm) 方法。使用算法的ID,而不是完整的描述性名称。

使用调用该方法 native:buffer 作为参数 (qgis:buffer 是的别名 native:buffer 并且也将起作用),您将获得以下描述:

>>> processing.algorithmHelp("native:buffer")
Buffer (native:buffer)

This algorithm computes a buffer area for all the features in an
input layer, using a fixed or dynamic distance.

The segments parameter controls the number of line segments to
use to approximate a quarter circle when creating rounded
offsets.

The end cap style parameter controls how line endings are handled
in the buffer.

The join style parameter specifies whether round, miter or
beveled joins should be used when offsetting corners in a line.

The miter limit parameter is only applicable for miter join
styles, and controls the maximum distance from the offset curve
to use when creating a mitered join.


----------------
Input parameters
----------------

INPUT: Input layer

   Parameter type: QgsProcessingParameterFeatureSource

   Accepted data types:
           - str: layer ID
           - str: layer name
           - str: layer source
           - QgsProcessingFeatureSourceDefinition
           - QgsProperty
           - QgsVectorLayer

DISTANCE: Distance

   Parameter type: QgsProcessingParameterDistance

   Accepted data types:
           - int
           - float
           - QgsProperty

SEGMENTS: Segments

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

END_CAP_STYLE: End cap style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Flat
           - 2: Square

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

JOIN_STYLE: Join style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Miter
           - 2: Bevel

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

MITER_LIMIT: Miter limit

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

DISSOLVE: Dissolve result

   Parameter type: QgsProcessingParameterBoolean

   Accepted data types:
           - bool
           - int
           - str
           - QgsProperty

OUTPUT: Buffered

   Parameter type: QgsProcessingParameterFeatureSink

   Accepted data types:
           - str: destination vector file, e.g. 'd:/test.shp'
           - str: 'memory:' to store result in temporary memory layer
           - str: using vector provider ID prefix and destination URI,
                  e.g. 'postgres:...' to store result in PostGIS table
           - QgsProcessingOutputLayerDefinition
           - QgsProperty

----------------
Outputs
----------------

OUTPUT:  <QgsProcessingOutputVectorLayer>
   Buffered

现在,您已经拥有了运行任何算法所需的一切。正如我们已经提到的,算法可以使用以下方式运行: run() 。其语法如下:

>>> processing.run(name_of_the_algorithm, parameters)

其中,参数是取决于要运行的算法的参数字典,并且正是 algorithmHelp() 方法为您提供了。

1 >>> processing.run("native:buffer", {'INPUT': '/data/lines.shp',
2               'DISTANCE': 100.0,
3               'SEGMENTS': 10,
4               'DISSOLVE': True,
5               'END_CAP_STYLE': 0,
6               'JOIN_STYLE': 0,
7               'MITER_LIMIT': 10,
8               'OUTPUT': '/data/buffers.shp'})

如果参数是可选的,并且您不想使用它,则不要将其包括在字典中。

如果未指定参数,将使用默认值。

根据参数类型的不同,值的引入方式也不同。下面的列表快速回顾了如何为每种类型的输入参数引入值:

  • 栅格层、矢量层或表格。只需使用带有标识要使用的数据对象的名称的字符串(它在QGIS目录中的名称)或文件名(如果对应的层未打开,则它将被打开,但不会添加到地图画布中)。如果您有一个表示该层的QGIS对象的实例,则还可以将其作为参数传递。

  • 枚举。如果算法具有枚举参数,则应使用整数值输入该参数的值。若要了解可用选项,可以使用 algorithmHelp() 命令,如上所述。例如, native:buffer 算法有一个名为JOIN_STYLE的枚举:

    JOIN_STYLE: Join style
    
       Parameter type: QgsProcessingParameterEnum
    
       Available values:
               - 0: Round
               - 1: Miter
               - 2: Bevel
    
       Accepted data types:
               - int
               - str: as string representation of int, e.g. '1'
               - QgsProperty
    

    在本例中,该参数有三个选项。请注意,排序是从零开始的。

  • 布尔型。使用 TrueFalse

  • 多路输入。该值是由分号分隔的输入描述符的字符串 (; )。与单个层或表的情况一样,每个输入描述符可以是数据对象名称或其文件路径。

  • 来自XXX的表字段。使用带有要使用的字段名称的字符串。此参数区分大小写。

  • 固定工作台。输入以逗号分隔的所有表值的列表 (, ),并用引号括起来 (" )。值从上一行开始,从左到右排列。您还可以使用表示表的二维值数组。

  • CRS.输入所需CRS的EPSG代码编号。

  • 范围。您必须将字符串与 xminxmaxyminymax 用逗号分隔的值 (, )。

布尔、文件、字符串和数值参数不需要任何额外的解释。

字符串、布尔值或数值等输入参数具有默认值。如果缺少相应的参数条目,则使用缺省值。

对于输出数据对象,键入用于保存它的文件路径,就像在工具箱中执行的操作一样。如果未指定输出对象,则将结果保存到临时文件中(如果是可选输出,则跳过)。文件的扩展名决定了文件格式。如果输入算法不支持的文件扩展名,则将使用该输出类型的默认文件格式,并将其相应的扩展名附加到给定的文件路径。

与从工具箱执行算法不同,如果使用从Python控制台执行相同的算法,则不会将输出添加到地图画布 run() ,但 runAndLoadResults() 都会这么做的。

这个 run() 方法返回一个字典,将一个或多个输出名称(算法描述中显示的名称)作为键,并将这些输出的文件路径作为值:

 1 >>> myresult = processing.run("native:buffer", {'INPUT': '/data/lines.shp',
 2               'DISTANCE': 100.0,
 3               'SEGMENTS': 10,
 4               'DISSOLVE': True,
 5               'END_CAP_STYLE': 0,
 6               'JOIN_STYLE': 0,
 7               'MITER_LIMIT': 10,
 8               'OUTPUT': '/data/buffers.shp'})
 9 >>> myresult['OUTPUT']
10 /data/buffers.shp

您可以通过将相应的文件路径传递给 load() 方法。或者你可以使用 runAndLoadResults() 而不是 run() 立即给它们装上子弹。

如果要从控制台打开算法对话框,可以使用 createAlgorithmDialog 方法。唯一的必填参数是算法名称,但您也可以定义参数字典,以便对话框自动填充:

 1 >>> my_dialog = processing.createAlgorithmDialog("native:buffer", {
 2               'INPUT': '/data/lines.shp',
 3               'DISTANCE': 100.0,
 4               'SEGMENTS': 10,
 5               'DISSOLVE': True,
 6               'END_CAP_STYLE': 0,
 7               'JOIN_STYLE': 0,
 8               'MITER_LIMIT': 10,
 9               'OUTPUT': '/data/buffers.shp'})
10 >>> my_dialog.show()

这个 execAlgorithmDialog 方法立即打开该对话框:

1 >>> processing.execAlgorithmDialog("native:buffer", {
2               'INPUT': '/data/lines.shp',
3               'DISTANCE': 100.0,
4               'SEGMENTS': 10,
5               'DISSOLVE': True,
6               'END_CAP_STYLE': 0,
7               'JOIN_STYLE': 0,
8               'MITER_LIMIT': 10,
9               'OUTPUT': '/data/buffers.shp'})

26.7.2. 创建脚本并从工具箱运行它们

您可以通过编写Python代码来创建自己的算法。处理脚本扩展 QgsProcessingAlgorithm ,因此您需要添加一些额外的代码行来实现强制函数。你可以找到 Create new script (干净的床单)和 Create New Script from Template (模板,包括的强制函数的代码 QgsProcessingAlgorithm )下的 Scripts 处理工具箱顶部的下拉菜单。将打开处理脚本编辑器,您应该在其中键入代码。将脚本从那里保存到 scripts 文件夹(打开保存文件对话框时的默认文件夹) .py 扩展应该创建相应的算法。

算法的名称(您将在工具箱中看到的算法)在代码中定义。

让我们来看一下下面的代码,它定义了一个处理算法,该算法在第一次对层进行平滑之后,在用户指定的向量层上使用用户定义的缓冲区距离执行缓冲区操作。

 1from qgis.core import (QgsProcessingAlgorithm,
 2       QgsProcessingParameterNumber,
 3       QgsProcessingParameterFeatureSource,
 4       QgsProcessingParameterFeatureSink)
 5
 6from qgis import processing
 7
 8class algTest(QgsProcessingAlgorithm):
 9    INPUT_BUFFERDIST = 'BUFFERDIST'
10    OUTPUT_BUFFER = 'OUTPUT_BUFFER'
11    INPUT_VECTOR = 'INPUT_VECTOR'
12
13    def __init__(self):
14        super().__init__()
15
16    def name(self):
17        return "algTest"
18
19    def displayName(self):
20        return "algTest script"
21
22    def createInstance(self):
23        return type(self)()
24
25    def initAlgorithm(self, config=None):
26        self.addParameter(QgsProcessingParameterFeatureSource(
27            self.INPUT_VECTOR, "Input vector"))
28        self.addParameter(QgsProcessingParameterNumber(
29            self.INPUT_BUFFERDIST, "Buffer distance",
30            QgsProcessingParameterNumber.Double,
31            100.0))
32        self.addParameter(QgsProcessingParameterFeatureSink(
33            self.OUTPUT_BUFFER, "Output buffer"))
34
35    def processAlgorithm(self, parameters, context, feedback):
36        #DO SOMETHING
37        algresult = processing.run("native:smoothgeometry",
38            {'INPUT': parameters[self.INPUT_VECTOR],
39             'ITERATIONS':2,
40             'OFFSET':0.25,
41             'MAX_ANGLE':180,
42             'OUTPUT': 'memory:'},
43            context=context, feedback=feedback, is_child_algorithm=True)
44        smoothed = algresult['OUTPUT']
45        algresult = processing.run('native:buffer',
46            {'INPUT': smoothed,
47            'DISTANCE': parameters[self.INPUT_BUFFERDIST],
48            'SEGMENTS': 5,
49            'END_CAP_STYLE': 0,
50            'JOIN_STYLE': 0,
51            'MITER_LIMIT': 10,
52            'DISSOLVE': True,
53            'OUTPUT': parameters[self.OUTPUT_BUFFER]},
54            context=context, feedback=feedback, is_child_algorithm=True)
55        buffered = algresult['OUTPUT']
56        return {self.OUTPUT_BUFFER: buffered}

在执行必要的导入后,请执行以下操作 QgsProcessingAlgorithm 指定了以下功能:

  • name() :算法的ID(小写)。

  • displayName() :算法的人类可读名称。

  • createInstance() :创建算法类的新实例。

  • initAlgorithm() :配置参数定义和输出定义。

    这里描述了算法的参数和输出。在这种情况下,输入的要素源、结果的要素接收器和缓冲距离的数字。

  • processAlgorithm() :做这项工作。

    在这里,我们首先运行 smoothgeometry 算法来平滑几何体,然后我们运行 buffer 平滑输出上的算法。为了能够从另一个算法中运行算法,我们必须将 is_child_algorithm 参数为 True 。您可以看到如何将输入和输出参数用作 smoothgeometrybuffer 算法。

有许多不同的参数类型可用于输入和输出。以下是按字母顺序排序的列表:

表 26.2 输入和输出算法参数类型列表

QgsProcessingParameterAggregate

QgsProcessingParameterAnnotationLayer

QgsProcessingParameterAuthConfig

QgsProcessingParameterBand

QgsProcessingParameterBoolean

QgsProcessingParameterColor

QgsProcessingParameterCoordinateOperation

QgsProcessingParameterCrs

QgsProcessingParameterDatabaseSchema

QgsProcessingParameterDatabaseTable

QgsProcessingParameterDateTime

QgsProcessingParameterDistance

QgsProcessingParameterEnum

QgsProcessingParameterExpression

QgsProcessingParameterExtent

QgsProcessingParameterFeatureSink

QgsProcessingParameterFeatureSource

QgsProcessingParameterField

QgsProcessingParameterFieldMapping

QgsProcessingParameterFile

QgsProcessingParameterFileDestination

QgsProcessingParameterFolderDestination

QgsProcessingParameterGeometry

QgsProcessingParameterLayout

QgsProcessingParameterLayoutItem

QgsProcessingParameterMapLayer

QgsProcessingParameterMapTheme

QgsProcessingParameterMatrix

QgsProcessingParameterMeshLayer

QgsProcessingParameterMultipleLayers

QgsProcessingParameterNumber

QgsProcessingParameterPoint

QgsProcessingParameterPointCloudAttribute

QgsProcessingParameterPointCloudLayer

QgsProcessingParameterProviderConnection

QgsProcessingParameterRange

QgsProcessingParameterRasterDestination

QgsProcessingParameterRasterLayer

QgsProcessingParameterScale

QgsProcessingParameterString

QgsProcessingParameterVectorDestination

QgsProcessingParameterVectorLayer

QgsProcessingParameterVectorTileDestination

QgsProcessingParameterVectorTileWriterLayers

构造函数的第一个参数是参数的名称,第二个参数是参数的描述(用于用户界面)。其余的构造函数参数是特定于参数类型的。

可以将输入转换为QGIS类 parameterAs 的功能 QgsProcessingAlgorithm 。例如,要获取以双精度形式提供的缓冲距离数字::

self.parameterAsDouble(parameters, self.INPUT_BUFFERDIST, context)).

这个 processAlgorithm 函数应返回一个字典,其中包含算法定义的每个输出的值。这允许从其他算法访问这些输出,包括包含在同一模型中的其他算法。

行为良好的算法应该定义和返回尽可能多的有意义的输出。当将算法作为较大模型的一部分运行时,非特征输出(如数字和字符串)非常有用,因为这些值可用作模型中后续算法的输入参数。考虑为处理的要素数量、遇到的无效要素数量、要素输出数量等添加数字输出。返回的输出越多,算法就越有用!

26.7.2.1. 反馈

这个 feedback 传递到的对象 processAlgorithm() 应用于用户反馈/交互。您可以使用 setProgress() 的功能 feedback 对象更新进度条(0到100)以通知用户算法的进度。如果您的算法需要很长时间才能完成,这将非常有用。

这个 feedback 对象提供了一个 isCanceled() 方法,应对其进行监视以允许用户取消算法。这个 pushInfo() 方法论 feedback 可用于向用户发送信息,以及 reportError() 对于将非致命错误推送给用户非常方便。

算法应避免使用其他形式向用户提供反馈,例如打印语句或记录 QgsMessageLog ,并且应该始终使用反馈对象来代替。这允许对算法进行详细的日志记录,并且也是线程安全的(这一点很重要,因为算法通常在后台线程中运行)。

26.7.2.2. 处理错误

如果算法遇到阻止其执行的错误,例如无效的输入值或无法或不应从中恢复的某些其他情况,则应引发 QgsProcessingException 。例如::

if feature['value'] < 20:
  raise QgsProcessingException('Invalid input value {}, must be >= 20'.format(feature['value']))

尽量避免提高 QgsProcessingException 对于非致命错误(例如,当要素具有空几何时),只需通过报告这些错误 feedback.reportError() 并跳过该功能。这有助于使您的算法“模型友好”,因为它避免了在遇到非致命错误时停止整个算法的执行。

26.7.2.3. 记录您的脚本

与模型的情况一样,您可以为您的脚本创建额外的文档,以解释它们做什么以及如何使用它们。

QgsProcessingAlgorithm 提供了 helpString()shortHelpString()helpUrl() 为此目的而运行的功能。指定/覆盖这些选项以向用户提供更多帮助。

shortDescription() 将鼠标悬停在工具箱中的算法上时,在工具提示中使用。

26.7.3. 执行前和执行后脚本挂钩

脚本还可以用作执行前和执行后的挂钩,分别在算法运行之前和之后运行。这可用于自动执行在执行算法时应执行的任务。

该语法与上面解释的语法相同,但增加了一个名为 alg 是可用的,表示刚刚执行(或即将执行)的算法。

General 组的处理选项对话框中,您将发现名为 Pre-execution scriptPost-execution script 其中可以输入在每种情况下要运行的脚本的文件名。