26.7. 콘솔에서 공간 처리 알고리즘 사용
고급 사용자는 콘솔을 통해 생산성을 향상시키는 것은 물론, 공간 처리 프레임워크의 다른 모든 GUI 항목을 통해서도 수행할 수 없는 복잡한 작업을 수행할 수 있습니다. 명령 줄 인터페이스를 사용해서 여러 알고리즘을 연결한 모델을 정의하고, 더욱 유연하고 강력한 작업 흐름을 생성하기 위한 반복문(for
) 및 조건문(if
)과 같은 부가적인 작업을 추가할 수 있습니다.
QGIS는 공간 처리 콘솔을 내장하고 있지 않지만, 그 대신 QGIS에 내장된 파이썬 콘솔 에서 모든 공간 처리 명령어를 사용할 수 있습니다. 즉 사용자의 콘솔 작업에 공간 처리 명령어를 포함시켜 콘솔에서 사용할 수 있는 다른 (QGIS API가 지원하는 메소드를 포함한) 모든 기능에 공간 처리 알고리즘을 연결할 수 있다는 의미입니다.
사용자가 파이썬 콘솔에서 실행하는 코드는, 비록 어느 특정한 공간 처리 메소드를 호출하지 않더라도, 다른 모든 알고리즘과 마찬가지로 향후 툴박스, 모델 설계자, 또는 기타 구성 요소에서 호출할 수 있는 새 알고리즘으로 변환할 수 있습니다. 사실, 툴박스에서 찾아볼 수 있는 알고리즘 가운데 일부는 단순한 스크립트일 뿐입니다.
이 절에서 QGIS 파이썬 콘솔에서 공간 처리 알고리즘을 사용하는 방법과 함께 파이썬으로 알고리즘을 작성하는 방법에 대해 설명하겠습니다.
26.7.1. 파이썬 콘솔에서 알고리즘 호출하기
사용자는 가장 먼저 공간 처리 함수를 다음 명령어로 가져와야 합니다:
>>> 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)
‘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 객체 인스턴스가 있을 경우, 해당 인스턴스도 파라미터로 넘겨줄 수 있습니다.
집합(enumeration): 알고리즘이 집합 파라미터를 받을 경우, 해당 파라미터의 값을 정수 값으로 입력해야 합니다. 사용할 수 있는 옵션을 알고 싶다면, 앞의 예시에서처럼
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
이 경우, 옵션 3개 가운데 하나를 이 파라미터로 입력할 수 있습니다. 순서가 0부터 시작한다는 점을 기억하십시오.
불(boolean):
True
또는False
를 사용하십시오.다중 입력: 쌍반점(
;
)으로 구분된 입력 서술자(descriptor)를 나타내는 문자열을 입력하십시오. 단일 레이어 또는 테이블의 경우, 데이터 객체의 이름 또는 파일 경로를 각 입력 서술자로 사용할 수 있습니다.XXX 테이블의 필드: 사용할 필드의 이름을 나타내는 문자열을 입력하십시오. 이 파라미터는 대소문자를 구별합니다.
고정 테이블: 큰따옴표(
"
)로 감싸고 쉼표(,
)로 구분한 모든 테이블 값의 목록을 입력하십시오. 이때 값은 상단 행부터 왼쪽에서 오른쪽 방향으로 입력합니다. 또는 테이블을 나타내는 값의 2차원 배열을 사용할 수도 있습니다.CRS: 원하는 좌표계의 EPGS 코드 번호를 입력하십시오.
범위(extent):
xmin
,xmax
,ymin
및ymax
값을 나타내는 쉼표(,
)로 구분한 문자열을 입력해야 합니다.
불(boolean), 파일, 문자열 및 숫자 파라미터에 대해서는 따로 설명이 필요없습니다.
문자열, 불, 또는 숫자 값과 같은 입력 파라미터에는 기본값이 있습니다. 해당 파라미터 항목이 빠져 있을 경우 기본값을 사용합니다.
산출 데이터 객체의 경우, 툴박스에서와 마찬가지로 산출물을 저장하기 위한 파일 경로를 입력하십시오. 산출물 객체를 지정하지 않을 경우 산출물을 임시 파일로 저장합니다. (또는 부가적인 산출물일 경우 건너뜁니다.) 파일의 확장자가 파일 포맷을 결정합니다. 알고리즘이 지원하지 않는 파일 확장자를 입력할 경우 해당 산출물 유형의 기본 파일 포맷을 사용하며, 입력한 파일 경로 끝에 해당 확장자를 덧붙일 것입니다.
툴박스에서 알고리즘을 실행할 때와는 달리, 파이썬 콘솔에서 run()
을 사용해서 동일한 알고리즘을 실행해도 산출물이 QGIS 맵 캔버스에 추가되지 않습니다. 그러나 runAndLoadResults()
로 실행하면 산출물을 맵 캔버스에 추가할 것입니다.
run()
메소드는 (알고리즘 설명에 표시되는) 하나 이상의 산출물 이름을 키로 삼고 해당 산출물의 파일 경로를 값으로 하는 목록(dictionary)을 반환합니다.
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()
메소드에 대응하는 파일 경로를 넘겨주면 피처 산출물을 불러올 수 있습니다. 또는 run()
대신 runAndLoadResults()
를 사용해서 즉시 불러올 수도 있습니다.
콘솔에서 알고리즘 대화창을 열고 싶다면 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. 스크립트 생성 및 툴박스에서 실행
파이썬 코드를 작성하면 사용자 고유의 알고리즘을 생성할 수 있습니다. 공간 처리 스크립트는 QgsProcessingAlgorithm
클래스를 확장하기 때문에, 필수 함수를 구현하는 코드를 몇 줄 추가해야 합니다. 공간 처리 툴박스 상단의 Scripts 드롭다운 메뉴에 Create new script (백지 상태) 및 Create New Script from Template (QgsProcessingAlgorithm
클래스의 필수 함수를 위한 코드를 포함하는 템플릿) 메뉴가 있습니다. 공간 처리 스크립트 편집기가 열리면 사용자의 코드를 입력해야 합니다. 이 편집기에서 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()
: ‘parameterDefinitions’ 및 ‘outputDefinitions’ 환경 설정여기에 알고리즘의 파라미터와 산출물을 설명합니다. 이 경우, 입력물용 피처 소스, 산출물용 피처 싱크(sink), 그리고 버퍼 거리용 숫자 값이 되겠군요.
processAlgorithm()
: 작업 실행먼저 도형을 평탄화시키기 위해
smoothgeometry
알고리즘을 실행한 다음, 평탄화된 산출물에buffer
알고리즘을 실행합니다. 어떤 알고리즘 내부에서 다른 알고리즘을 실행시키려면is_child_algorithm
인자를True
로 설정해야 합니다. 입력 및 산출 파라미터를 어떻게smoothgeometry
및buffer
알고리즘에 파라미터로 사용하는지 볼 수 있을 겁니다.
입력물과 산출물로 사용할 수 있는 서로 다른 파라미터 유형이 많이 있습니다. 다음은 알파벳순으로 정렬한 목록입니다:
구성자(constructor)가 받는 첫 번째 파라미터는 파라미터의 이름이며, 두 번째는 파라미터의 (사용자 인터페이스용) 설명입니다. 나머지 구성자 파라미터들은 파라미터 유형에 특화되어 있습니다.
QgsProcessingAlgorithm
클래스의 parameterAs
함수를 사용하면 입력물을 QGIS 클래스로 변환할 수 있습니다. 예를 들어 버퍼 거리를 지정하는 숫자를 실수형(double)으로 받으려면:
self.parameterAsDouble(parameters, self.INPUT_BUFFERDIST, context)).
processAlgorithm
함수는 알고리즘이 정의한 모든 산출물에 대한 값을 담고 있는 목록을 반환해야 합니다. 이렇게 해서 동일 모델 안에 있는 다른 알고리즘을 포함한 다른 알고리즘이 이 산출물들에 접근할 수 있게 됩니다.
제대로 동작하는 알고리즘은 의미가 통하는만큼의 산출물을 정의하고 반환해야 합니다. 숫자 및 문자열 같은 피처가 아닌 산출물은 사용자 알고리즘을 더 큰 모델의 일부로 실행하는 경우 아주 유용합니다. 그 값을 모델 내부의 바로 다음 알고리즘의 입력 파라미터로 사용할 수 있기 때문입니다. 공간 처리된 피처의 개수, 실행중 찾아낸 유효하지 않은 피처의 개수, 피처 산출물의 개수 등과 같은 값을 위해 숫자형 산출물을 추가하는 것도 좋겠죠. 반환되는 산출물이 많을수록, 사용자 알고리즘도 더 유용해지니까요!
26.7.2.1. 피드백
processAlgorithm()
메소드에 넘겨지는 feedback()
객체는 사용자 피드백/대화형 작업에 사용되어야 합니다. feedback()
객체의 setProgress()
함수를 사용하면 알고리즘의 진행도를 알려주는 진행 과정 막대를 (0에서 100 사이의 값으로) 업데이트할 수 있습니다. 사용자 알고리즘이 완료까지 오래 걸리는 경우 매우 유용한 함수입니다.
feedback()
객체는 사용자가 알고리즘을 취소할 수 있게 하려면 감시해야 하는 isCanceled()
메소드를 제공합니다. feedback()
객체의 pushInfo()
메소드를 사용해서 사용자에게 정보를 전달할 수 있고, reportError()
메소드는 사용자에게 심각하지 않은(non-fatal) 오류를 푸시하는 데 편리합니다.
알고리즘은 가급적 서술을 인쇄하거나 QgsMessageLog
에 로그를 작성하는 등의 다른 형태로 사용자에게 피드백을 제공해서는 안 되며, 대신 언제나 피드백 객체를 사용해야 합니다. 피드백 객체를 사용하면 알고리즘이 장황한 로그 작업을 할 수 있으며, 스레드 편에서도 안전합니다. (알고리즘이 일반적으로 배경 스레드에서 실행된다는 점을 감안하면 아주 중요한 이유죠.)
26.7.2.2. 오류 처리하기
사용자 알고리즘의 실행을 방해하는 오류가 발생한 경우, 예를 들어 입력값이 유효하지 않거나 다른 조건이 맞지 않아 복구되서는 안 되고 될 수도 없을 때, QgsProcessingException
을 발생시켜야 합니다. 예를 들면:
if feature['value'] < 20:
raise QgsProcessingException('Invalid input value {}, must be >= 20'.format(feature['value']))
심각하지 않은 오류인 경우 (예를 들어 피처가 NULL 도형을 가진 경우) QgsProcessingException
을 발생시키지 말고 대신 feedback.reportError()
를 통해 오류를 보고만 한 다음 해당 피처를 건너뛰는 편이 좋습니다. 이렇게 하면 사용자 알고리즘이 “모델 친화적(model-friendly)” 이 됩니다. 심각하지 않은 오류인 경우 전체 알고리즘 실행을 정지하지 않기 때문이죠.
26.7.2.3. 사용자 스크립트 문서 작성하기
모델의 경우와 마찬가지로, 사용자 스크립트를 위해 그 목적 및 사용법을 설명하는 추가 문서를 생성할 수 있습니다.
QgsProcessingAlgorithm()
이 그 목적을 위해 helpString()
, shortHelpString()
및 helpUrl()
함수를 제공합니다. 사용자에게 더 많은 도움말을 제공하려면 이 함수들을 지정하거나 무시하십시오.
툴박스에 있는 알고리즘 위로 커서를 가져다대면 나타나는 툴팁에는 shortDescription()
을 사용합니다.
26.7.3. 실행전 및 실행후 스크립트 후크
스크립트를 알고리즘을 실행하기 전, 실행한 후에 실행되는 실행전(pre-execution) 및 실행후(post-execution) 후크(hook)로 사용할 수도 있습니다. 후크는 알고리즘을 실행할 때마다 수행해야 하는 작업을 자동화하기 위해 사용됩니다.
후크의 문법은 앞에서 설명한 문법과 동일하지만, alg
라는 또다른 전체 수준 변수를 사용할 수 있습니다. alg
는 방금 실행된 (또는 곧 실행될) 알고리즘을 나타내는 변수입니다.
공간 처리 옵션 대화창의 General 그룹에서 Pre-execution script 및 Post-execution script 라는 두 옵션을 볼 수 있는데, 이 두 옵션에 각각의 경우 실행될 스크립트의 파일명을 입력할 수 있습니다.