-->

Advertisement

HƯỚNG DẪN BẮT ĐẦU LẬP TRÌNH PYTHON TOOLBOX (.PYT) TRONG ARCGIS PRO

Python Toolbox, hay file .pyt, là một dạng Toolbox của ArcGIS Pro được viết hoàn toàn bằng Python. Với PYT, bạn có thể tạo các công cụ có giao diện nhập tham số giống các công cụ Geoprocessing mặc định của ArcGIS.

PYT đặc biệt phù hợp để tự động hóa các công việc như: xử lý Feature Class, kiểm tra dữ liệu, chuẩn hóa GDB, gán hệ tọa độ, cập nhật thuộc tính, xử lý nhiều layer và xây dựng các quy trình GIS lặp lại.

Người dùng chọn tham số → ArcGIS truyền dữ liệu vào Tool → Python/ArcPy xử lý → Tool trả kết quả và thông báo

1. Chuẩn bị môi trường

Khi cài ArcGIS Pro, Python và thư viện arcpy đã được cài kèm. Vì vậy, đối với phần lớn công cụ PYT cơ bản, bạn không cần cài Python riêng.

Bạn chỉ cần một trình soạn thảo mã như:

  • Visual Studio Code
  • Notepad++
  • PyCharm
  • Hoặc Notepad nếu chỉ sửa file đơn giản
Nên dùng Visual Studio Code vì dễ đọc code, có tô màu cú pháp và hỗ trợ tìm lỗi tốt hơn.

2. Tạo file PYT đầu tiên

Tạo một file mới và lưu với phần mở rộng:

MyTools.pyt

Không lưu thành:

MyTools.pyt.txt

Một file PYT tối thiểu gồm hai phần chính:

import arcpy


class Toolbox(object):

    def __init__(self):
        self.label = "My GIS Tools"
        self.alias = "mygistools"

        self.tools = [
            HelloTool
        ]


class HelloTool(object):

    def __init__(self):
        self.label = "Hello Tool"
        self.description = "Cong cu PYT dau tien."

        self.canRunInBackground = False


    def getParameterInfo(self):
        return []


    def execute(self, parameters, messages):

        arcpy.AddMessage("Xin chao ArcGIS Pro!")

        return

3. Hiểu cấu trúc của file PYT

3.1. Import thư viện

import arcpy

arcpy là thư viện Python chính của ArcGIS Pro. Nó cho phép Python gọi các công cụ GIS như:

arcpy.management.CopyFeatures()
arcpy.management.DefineProjection()
arcpy.management.AddField()
arcpy.management.Delete()
arcpy.analysis.Buffer()

Ngoài arcpy, bạn thường sử dụng thêm các thư viện Python chuẩn:

import os
import sys
import math
import re
import json
import csv
import datetime

4. Class Toolbox là gì?

Class Toolbox dùng để khai báo Toolbox và danh sách các công cụ có trong file PYT.

class Toolbox(object):

    def __init__(self):

        self.label = "GIS Tools"
        self.alias = "gistools"

        self.tools = [
            Tool1,
            Tool2,
            Tool3
        ]

Nếu file PYT chứa ba công cụ thì ArcGIS sẽ hiển thị:

GIS Tools
│
├── Tool 1
├── Tool 2
└── Tool 3

5. Class của một Tool

Mỗi công cụ trong PYT thường là một class riêng.

class CheckGeometry(object):

    def __init__(self):

        self.label = "Check Geometry"
        self.description = "Kiem tra loi hinh hoc."

        self.canRunInBackground = False

Trong đó:

Thuộc tính Ý nghĩa
self.label Tên hiển thị của công cụ trong ArcGIS Pro.
self.description Mô tả chức năng của công cụ.
self.canRunInBackground Quy định công cụ có chạy nền hay không.

6. Khai báo tham số đầu vào

Các tham số hiển thị trong giao diện Geoprocessing được khai báo trong hàm:

def getParameterInfo(self):

Ví dụ chọn một Feature Class:

def getParameterInfo(self):

    input_fc = arcpy.Parameter(
        displayName="Feature Class đầu vào",
        name="input_fc",
        datatype="GPFeatureLayer",
        parameterType="Required",
        direction="Input"
    )

    return [input_fc]

Khi mở Tool, ArcGIS sẽ tạo một ô chọn layer tương ứng.

7. Một số kiểu tham số thường dùng

Datatype Dùng cho
GPString Chuỗi văn bản.
GPLong Số nguyên.
GPDouble Số thực.
GPBoolean True / False.
GPFeatureLayer Feature Layer trong Map.
DEFeatureClass Feature Class.
DEWorkspace Folder hoặc Geodatabase.
GPField Field của một bảng/layer.
DEFile File bất kỳ.

8. Tạo danh sách xổ xuống

Ví dụ người dùng chọn tỉnh/thành phố:

province = arcpy.Parameter(
    displayName="Tỉnh / Thành phố",
    name="province",
    datatype="GPString",
    parameterType="Required",
    direction="Input"
)

province.filter.type = "ValueList"

province.filter.list = [
    "Hà Nội",
    "Hải Phòng",
    "Quảng Ninh",
    "Đà Nẵng"
]

ArcGIS sẽ hiển thị danh sách dropdown thay vì cho nhập tự do.

9. Chọn nhiều dữ liệu cùng lúc

Nếu muốn người dùng chọn nhiều GDB:

gdbs = arcpy.Parameter(
    displayName="Các File Geodatabase",
    name="gdbs",
    datatype="DEWorkspace",
    parameterType="Required",
    direction="Input",
    multiValue=True
)

Điểm cần chú ý:

multiValue=True

cho phép một tham số chứa nhiều giá trị.

10. Hàm execute()

Hàm execute() là nơi thực hiện xử lý chính.

def execute(self, parameters, messages):

    input_fc = parameters[0].valueAsText

    arcpy.AddMessage(
        "Đang xử lý: {}".format(input_fc)
    )

    return

Các tham số được truy cập theo thứ tự trong danh sách trả về của getParameterInfo().

Ví dụ:

return [
    province,
    input_gdb,
    output_folder
]

thì trong execute():

province = parameters[0].valueAsText
input_gdb = parameters[1].valueAsText
output_folder = parameters[2].valueAsText

11. Định nghĩa hàm riêng

Không nên viết toàn bộ xử lý trong execute(). Với công cụ lớn, nên chia thành nhiều hàm nhỏ.

Ví dụ:

def get_feature_classes(gdb):

    feature_classes = []

    for dirpath, dirnames, filenames in arcpy.da.Walk(
        gdb,
        datatype="FeatureClass"
    ):

        for filename in filenames:

            fc = os.path.join(
                dirpath,
                filename
            )

            feature_classes.append(fc)

    return feature_classes

Sau đó gọi trong execute():

feature_classes = get_feature_classes(gdb)

for fc in feature_classes:
    arcpy.AddMessage(fc)
Chia code thành nhiều hàm nhỏ giúp dễ kiểm tra lỗi, dễ bảo trì và có thể tái sử dụng.

12. Thư viện os

os là thư viện rất thường dùng để xử lý đường dẫn và thư mục.

import os

Nối đường dẫn:

path = os.path.join(
    folder,
    "QuyHoach.gdb"
)

Kiểm tra file tồn tại:

if os.path.exists(path):
    print("File tồn tại")

Lấy thư mục Documents:

documents = os.path.join(
    os.path.expanduser("~"),
    "Documents"
)

Ví dụ đường dẫn ArcGIS Coordinate Systems:

prj_folder = os.path.join(
    os.path.expanduser("~"),
    "Documents",
    "ArcGIS",
    "Coordinate Systems"
)

13. Thư viện re

re dùng để tìm kiếm và xử lý chuỗi theo mẫu.

import re

Ví dụ lấy đường kính từ chuỗi:

text = "D450-0.25%-L=200M"

match = re.search(
    r"D(\d+)",
    text
)

if match:
    diameter = match.group(1)

Kết quả:

450

14. Thư viện math

Dùng cho các phép tính toán học.

import math

Ví dụ:

angle_rad = math.radians(45)

sin_value = math.sin(angle_rad)

distance = math.sqrt(
    dx * dx + dy * dy
)

15. Thư viện json

json hữu ích nếu muốn lưu cấu hình của Tool ra file.

import json

Ví dụ cấu hình:

config = {
    "province": "Hải Phòng",
    "central_meridian": 105.75
}

with open(
    "config.json",
    "w",
    encoding="utf-8"
) as f:

    json.dump(
        config,
        f,
        ensure_ascii=False,
        indent=4
    )

16. arcpy.env

arcpy.env dùng để thiết lập môi trường xử lý.

Ví dụ:

arcpy.env.overwriteOutput = True

Cho phép ghi đè dữ liệu đầu ra.

Thiết lập workspace:

arcpy.env.workspace = gdb

Sau đó các hàm như:

arcpy.ListFeatureClasses()

sẽ tìm dữ liệu trong GDB đó.

17. arcpy.Describe()

Describe dùng để đọc thông tin của một dataset.

desc = arcpy.Describe(fc)

Ví dụ lấy:

shape_type = desc.shapeType
spatial_ref = desc.spatialReference
has_z = desc.hasZ
has_m = desc.hasM

Đây là một trong những hàm rất hữu ích khi viết các công cụ kiểm tra dữ liệu.

18. arcpy.ListFields()

Để lấy danh sách field:

fields = arcpy.ListFields(fc)

for field in fields:

    arcpy.AddMessage(
        "{} - {}".format(
            field.name,
            field.type
        )
    )

Kiểm tra một field có tồn tại:

field_names = [
    f.name.lower()
    for f in arcpy.ListFields(fc)
]

if "ghichu" in field_names:
    arcpy.AddMessage("Có field ghiChu")

19. Cursor trong ArcPy

Cursor dùng để đọc hoặc chỉnh sửa từng đối tượng.

SearchCursor

with arcpy.da.SearchCursor(
    fc,
    ["OBJECTID", "tenDoiTuong"]
) as cursor:

    for row in cursor:

        objectid = row[0]
        name = row[1]

UpdateCursor

with arcpy.da.UpdateCursor(
    fc,
    ["ghiChu"]
) as cursor:

    for row in cursor:

        row[0] = "Đã kiểm tra"

        cursor.updateRow(row)
UpdateCursor thay đổi trực tiếp dữ liệu. Nên sao lưu GDB trước khi thử các Tool mới.

20. Một số công cụ ArcPy thường dùng

Thêm Field

arcpy.management.AddField(
    fc,
    "ghiChu",
    "TEXT",
    field_length=250
)

Xóa dữ liệu

arcpy.management.DeleteRows(fc)

Copy Feature

arcpy.management.CopyFeatures(
    input_fc,
    output_fc
)

Append dữ liệu

arcpy.management.Append(
    input_fc,
    target_fc,
    "NO_TEST"
)

Define Projection

arcpy.management.DefineProjection(
    fc,
    spatial_reference
)

Project

arcpy.management.Project(
    input_fc,
    output_fc,
    spatial_reference
)
Define Projection chỉ khai báo hệ tọa độ. Project mới thực sự chuyển đổi tọa độ.

21. Hiển thị thông báo cho người dùng

Thông báo thông thường:

arcpy.AddMessage(
    "Đang xử lý..."
)

Cảnh báo:

arcpy.AddWarning(
    "Feature Class chưa có hệ tọa độ."
)

Lỗi:

arcpy.AddError(
    "Không tìm thấy GDB."
)

Nên dùng các hàm này thay cho print() trong PYT vì thông báo sẽ xuất hiện trực tiếp trong cửa sổ Geoprocessing.

22. Xử lý lỗi bằng try / except

Một Tool tốt không nên dừng đột ngột khi gặp lỗi.

try:

    arcpy.management.DefineProjection(
        fc,
        spatial_reference
    )

    arcpy.AddMessage(
        "Hoàn thành: {}".format(fc)
    )

except Exception as ex:

    arcpy.AddError(
        "Lỗi: {}".format(ex)
    )

Khi xử lý nhiều Feature Class, bạn có thể bắt lỗi từng Feature Class để một lỗi không làm dừng toàn bộ Tool.

23. Một Tool mẫu hoàn chỉnh

Ví dụ dưới đây cho phép chọn một GDB và liệt kê toàn bộ Feature Class, kể cả Feature Class nằm trong Feature Dataset.

import arcpy
import os


class Toolbox(object):

    def __init__(self):

        self.label = "GIS Training Tools"
        self.alias = "gistraining"

        self.tools = [
            ListFeatureClasses
        ]


class ListFeatureClasses(object):

    def __init__(self):

        self.label = "List Feature Classes"
        self.description = (
            "Liệt kê toàn bộ Feature Class "
            "trong File Geodatabase."
        )

        self.canRunInBackground = False


    def getParameterInfo(self):

        gdb = arcpy.Parameter(
            displayName="File Geodatabase",
            name="input_gdb",
            datatype="DEWorkspace",
            parameterType="Required",
            direction="Input"
        )

        return [gdb]


    def execute(
        self,
        parameters,
        messages
    ):

        gdb = parameters[0].valueAsText

        arcpy.AddMessage(
            "GDB: {}".format(gdb)
        )

        count = 0

        for (
            dirpath,
            dirnames,
            filenames
        ) in arcpy.da.Walk(
            gdb,
            datatype="FeatureClass"
        ):

            for filename in filenames:

                fc = os.path.join(
                    dirpath,
                    filename
                )

                count += 1

                arcpy.AddMessage(
                    "{}. {}".format(
                        count,
                        fc
                    )
                )

        arcpy.AddMessage(
            "Tổng số Feature Class: {}".format(
                count
            )
        )

        return

24. Thêm file PYT vào ArcGIS Pro

Trong ArcGIS Pro:

Catalog
→ Toolboxes
→ Right Click
→ Add Toolbox
→ Chọn file .pyt

Tool sẽ xuất hiện giống các Geoprocessing Tool bình thường.

25. Sửa code và Refresh

Sau khi chỉnh sửa file PYT trong VS Code:

Save
→ ArcGIS Pro
→ Catalog
→ Right Click Toolbox
→ Refresh

Không cần Add Toolbox lại từ đầu.

26. Cách tổ chức code khi Tool bắt đầu lớn

Không nên để tất cả xử lý trong một hàm.

Cấu trúc nên hướng tới:

import arcpy
import os


# =========================
# CONSTANTS
# =========================

DEFAULT_FOLDER = "..."


# =========================
# FUNCTIONS
# =========================

def get_feature_classes(gdb):
    pass


def check_spatial_reference(fc):
    pass


def define_projection(fc, sr):
    pass


# =========================
# TOOLBOX
# =========================

class Toolbox(object):
    pass


# =========================
# TOOLS
# =========================

class DefineVN2000(object):
    pass


class CheckGeometry(object):
    pass


class CheckZM(object):
    pass

Cấu trúc này giúp file PYT dễ đọc hơn khi phát triển thành một bộ công cụ lớn.

27. Một số nguyên tắc quan trọng cho người mới

  • Viết Tool nhỏ trước, sau đó mới mở rộng.
  • Dùng arcpy.AddMessage() để biết Tool đang xử lý đến đâu.
  • Luôn kiểm tra dữ liệu tồn tại trước khi xử lý.
  • Không thay đổi dữ liệu gốc khi chưa kiểm thử Tool.
  • Tách các phần xử lý thành các hàm riêng.
  • Đặt tên biến rõ nghĩa.
  • Dùng try / except cho các bước có khả năng lỗi.
  • Kiểm thử với GDB nhỏ trước khi chạy hàng loạt.

28. Lộ trình học PYT đề xuất

Với người mới bắt đầu, không cần học toàn bộ Python trước. Có thể học theo đúng nhu cầu ArcGIS.

Bước 1: Python cơ bản
↓
Biến - if - for - list - dict - function
↓
Bước 2: ArcPy cơ bản
↓
Describe - ListFields - Cursor - Management
↓
Bước 3: PYT
↓
Parameter - execute - updateParameters
↓
Bước 4: Tool xử lý GDB
↓
Bước 5: Bộ công cụ GIS hoàn chỉnh

29. Bài tập thực hành đầu tiên

Sau khi hiểu cấu trúc cơ bản, có thể lần lượt viết các Tool:

  1. Chọn một Feature Class và hiển thị tên.
  2. Đọc danh sách Field.
  3. Kiểm tra Feature Class có Z/M hay không.
  4. Chọn GDB và liệt kê toàn bộ Feature Class.
  5. Kiểm tra Spatial Reference.
  6. Define Projection cho Feature Class.
  7. Chọn nhiều GDB và xử lý hàng loạt.
  8. Tạo Tool VN-2000 theo tỉnh/thành phố.
Nếu làm được 8 bài tập trên, bạn đã có đủ nền tảng để xây dựng phần lớn các công cụ PYT phục vụ kiểm tra, chuẩn hóa và tự động hóa dữ liệu GIS trong ArcGIS Pro.

30. Kết luận

Khi mới bắt đầu PYT, điều quan trọng nhất không phải là học thật nhiều cú pháp Python, mà là hiểu được cấu trúc:

Parameter
→ Lấy dữ liệu đầu vào
→ Kiểm tra dữ liệu
→ Gọi ArcPy
→ Xử lý
→ Thông báo kết quả

Sau khi nắm được cấu trúc này, bạn có thể dần phát triển từ một Tool đơn giản thành một bộ công cụ chuyên nghiệp dùng chung trong ArcGIS Pro.