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.
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
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)
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)
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
)
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 / exceptcho 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.
↓
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:
- Chọn một Feature Class và hiển thị tên.
- Đọc danh sách Field.
- Kiểm tra Feature Class có Z/M hay không.
- Chọn GDB và liệt kê toàn bộ Feature Class.
- Kiểm tra Spatial Reference.
- Define Projection cho Feature Class.
- Chọn nhiều GDB và xử lý hàng loạt.
- Tạo Tool VN-2000 theo tỉnh/thành phố.
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.
