BAB 32: Dari QGIS ke ArcPy dan Kembali: Pola, Padanan, dan Cara Menerjemahkan
Studi kasus: "Skrip ini jalan di QGIS. Bisakah dibuat versi ArcGIS-nya?" #
Anda sudah punya skrip PyQGIS yang menghitung luas, sempadan sungai, dan titik panas per KPH. Kantor cabang meminta versi yang jalan di ArcGIS. Anda tidak perlu menulis dari nol. Pekerjaannya sama, hanya "bahasa alat"-nya yang berbeda. Kabar baiknya: setelah Bab 30 dan 31, Anda sudah punya kamus kecil di kepala. Bab ini merapikan kamus itu menjadi tabel, lalu mengajarkan cara menerjemahkan dengan langkah yang bisa diulang.
Konsep: menerjemahkan skrip dalam tiga kalimat #
Menerjemahkan skrip itu seperti menerjemahkan resep dari bahasa lain. Bahan dan urutan masaknya sama, tetapi nama bumbu dan alat dapurnya berbeda. Ada tiga lapis yang perlu Anda terjemahkan: gaya Python (Pro lawan ArcMap), nama alat (QGIS lawan ArcPy), dan cara menunjuk data (layer dalam proyek lawan jalur teks).

Empat istilah baru yang perlu Anda kenal sekarang:
- Padanan: dua penulisan di dua alat yang mengerjakan hal yang sama.
- Alat (tool): satu pekerjaan siap pakai, misalnya penyangga. Di QGIS dipanggil lewat
processing.run, di ArcGIS lewatarcpy.<kotak alat>.<Alat>. - Keluaran sementara: hasil antara yang tidak ditulis ke berkas. Di QGIS
"TEMPORARY_OUTPUT", di ArcGISmemory\nama. - Angka acuan: hasil yang Anda ketahui benar dari data contoh, misalnya luas KPH Alpha 4,0 hektare. Angka ini dipakai untuk menguji terjemahan Anda.
Tabel padanan: membaca data dan atribut #
Tabel ini diambil dari Skrip 31.1 dan skrip PyQGIS b1_01 dan b1_02 (Bab 14). Kolom ArcPy memakai penulisan ArcGIS Pro.

| Pekerjaan | PyQGIS | ArcPy (Pro) |
|---|---|---|
| Membuka layer vektor | QgsVectorLayer(DATA + "/Batas_KPH.gpkg", "Batas_KPH", "ogr") | nama teks "Batas_KPH.shp" di folder kerja arcpy.env.workspace |
| Memeriksa data terbuka | layer.isValid() | arcpy.Exists(jalur) |
| Jumlah fitur | layer.featureCount() | int(arcpy.management.GetCount(batas)[0]) |
| Nama kolom | [f.name() for f in layer.fields()] | [f.name for f in arcpy.ListFields(batas)] |
| Sistem koordinat | layer.crs().authid() | arcpy.Describe(batas).spatialReference.factoryCode |
| Jenis geometri | QgsWkbTypes.displayString(layer.wkbType()) | arcpy.Describe(batas).shapeType |
| Membaca tiap baris | for fitur in batas.getFeatures(): | with arcpy.da.SearchCursor(batas, [...]) as kursor: |
| Isi satu kolom | fitur["NAMA_KPH"] | satu isian di baris kursor |
| Luas satu fitur | fitur.geometry().area() | kolom khusus "SHAPE@AREA" |
Dua hal yang mudah luput. Pertama, authid() mengembalikan teks EPSG:32749, sedangkan factoryCode mengembalikan angka 32749. Perbandingan == "EPSG:32749" di PyQGIS menjadi == 32749 di ArcPy. Kedua, kursor ArcPy mengembalikan isian menurut urutan kolom yang Anda daftarkan, sedangkan fitur QGIS dibaca dengan nama kolom.
Tabel padanan: raster #
Tabel ini diambil dari Skrip 31.1, 31.2, dan 31.3, serta skrip PyQGIS b2_03 dan b3_02 (Bab 21).
| Pekerjaan | PyQGIS | ArcPy (Pro) |
|---|---|---|
| Membuka raster | QgsRasterLayer(jalur, nama, "gdal") | arcpy.Raster(jalur) |
| Lebar dan tinggi | r.width() dan r.height() | r.width dan r.height |
| Jumlah band | r.bandCount() | r.bandCount |
| Ukuran piksel | r.rasterUnitsPerPixelX() | r.meanCellWidth |
| Satu band | "Citra_KPH@4" di dalam ekspresi | Raster(DATA + r"\Citra_KPH.tif\Band_4") |
| NDVI | ekspresi ("Citra_KPH@4" - "Citra_KPH@1") / (...) lewat native:rastercalc | (nir - merah) / (nir + merah) dengan Float(...) |
| Tinggi tajuk (CHM) | ekspresi "DSM@1" - "DTM@1" | Raster(DSM) - Raster(DTM) |
| Rata-rata per poligon | native:zonalstatisticsfb, kolom hasil ndvi_mean | ZonalStatisticsAsTable(..., "DATA", "MEAN"), kolom hasil MEAN |
| Memotong raster | gdal:cliprasterbymasklayer | ExtractByMask(raster, batas).save(...) |
Perhatikan tanda kurung pada baris kedua sampai keempat. Di PyQGIS, lebar raster adalah fungsi: r.width(). Di ArcPy, ia sifat: r.width tanpa kurung. Salah menulis kurung memberi galat. Dokumentasi Esri mencatat bahwa ExtractByMask mengembalikan objek raster yang disimpan lewat .save(), sedangkan hasil native:rastercalc di skrip Bab 21 berupa teks jalur yang kemudian dibungkus jadi layer. [CEK]
Tabel padanan: alat vektor #
Tabel ini diambil dari Skrip 31.2, 31.3, dan 31.4, serta skrip PyQGIS b2_02, b3_02, dan b4_02 (Bab 21 dan 22).
| Pekerjaan | PyQGIS | ArcPy (Pro) |
|---|---|---|
| Memanggil alat | processing.run("native:buffer", {...})["OUTPUT"] | arcpy.analysis.Buffer(...) |
| Cara memberi parameter | kamus: nama parameter lalu nilai | isian berurutan atau kata kunci |
| Penyangga 30 m | "DISTANCE": 30 | "30 Meters" |
| Gabungkan semua penyangga | "DISSOLVE": True | dissolve_option="ALL" |
| Irisan | native:intersection dengan INPUT dan OVERLAY | arcpy.analysis.Intersect([a, b], keluaran) |
| Jumlah titik per poligon | native:countpointsinpolygon | arcpy.analysis.SpatialJoin(...) lalu kolom Join_Count |
| Memilih satu KPH | native:extractbyexpression | arcpy.analysis.Select(batas, keluaran, "NAMA_KPH = '%s'" % nama) |
| Mengubah sistem koordinat | native:reprojectlayer | arcpy.management.Project(...) |
| Keluaran sementara | "TEMPORARY_OUTPUT" | memory\nama |
Dua hal lain yang mudah luput. Pertama, hasil alat QGIS berupa kamus, jadi Anda mengambil ["OUTPUT"]. Di ArcPy tidak ada kamus: Anda sendiri yang menyebut nama keluaran, lalu memakai nama itu di langkah berikutnya. Kedua, "DISTANCE": 30 di QGIS mengikuti satuan sistem koordinat layer. Skrip PyQGIS Anda mencatatnya dalam komentar: satuannya meter karena sistem koordinatnya UTM. Di ArcPy, satuan ikut ditulis di dalam teks jarak.
Tabel padanan: peta, galat, dan berkas #
Tabel ini diambil dari Skrip 31.1, 31.4, dan 31.5, skrip M1 di Bab 30, serta skrip PyQGIS b1_03, b4_02, dan b7_01 (Bab 14, 22, dan 23).
| Pekerjaan | PyQGIS | ArcPy (Pro) | ArcPy (ArcMap) |
|---|---|---|---|
| Proyek yang terbuka | QgsProject.instance() | arcpy.mp.ArcGISProject("CURRENT") | arcpy.mapping.MapDocument("CURRENT") |
| Menambah layer | proyek.addMapLayer(layer) | peta.addDataFromPath(jalur) | arcpy.mapping.AddLayer(df, arcpy.mapping.Layer(jalur)) |
| Mengambil layer | proyek.mapLayersByName("Batas_KPH")[0] | peta.listLayers("Batas_KPH")[0] | arcpy.mapping.ListLayers(mxd, "Batas_KPH", df)[0] |
| Menyimpan | proyek.write(berkas) | aprx.save() | mxd.save() |
| Menangkap galat alat | except Exception as e: | except arcpy.ExecuteError: | except arcpy.ExecuteError: |
| Pesan galat alat | str(e) | arcpy.GetMessages(2) | arcpy.GetMessages(2) |
| Menulis CSV | open(..., "w", newline="", encoding="utf-8") | open(..., "w", newline="") | open(..., "wb") |
| Membuat folder | os.makedirs(HASIL, exist_ok=True) | os.makedirs(..., exist_ok=True) | if not os.path.exists(...): os.makedirs(...) |
Bedanya penting pada baris "Menyimpan". proyek.write(berkas) menulis ke berkas yang Anda sebut. Perintah aprx.save() menyimpan perubahan ke proyek yang sedang terbuka, yaitu menimpa. Dokumentasi Esri menyediakan saveACopy(nama_berkas) untuk menyimpan salinan. [CEK]
Cara menerjemahkan skrip: enam langkah #

- Baca pola skrip dulu. Hampir semua skrip di buku ini berbentuk empat tahap: tetapkan lokasi data, cek sifat data, ulangi tiap baris, lalu simpan atau tampilkan. Tulis keempat tahap itu di kertas.
- Tandai bagian Python murni. Perulangan
for,if, kamus, daftar,round, danprinttidak perlu diterjemahkan. Cukup pindahkan. - Cari padanan tiap alat. Pakai tabel di bab ini. Bila alat tidak ada di tabel, buka dokumentasi alat itu. Cek urutan isiannya, jangan menebak.
- Ganti cara menunjuk data. QGIS memakai layer yang dimuat, ArcPy memakai jalur teks atau nama di folder kerja. Karena itu tentukan
arcpy.env.workspacedan nama keluaran sementara. - Sesuaikan gaya Python. Bila tujuannya ArcMap, terapkan beda Python 2.7:
printdengan%,10000.0,.format, danarcpy.mapping. - Uji kecil dan cocokkan angka acuan. Jalankan dengan data contoh. Bandingkan hasil dengan angka yang sudah Anda ketahui.
Contoh terjemahan 1: membaca luas tiap KPH #
Bagian ini dari skrip PyQGIS b1_02_baca_atribut.py, baris 16 sampai 20:
for fitur in batas.getFeatures():
nama = fitur["NAMA_KPH"]
luas_ha = fitur.geometry().area() / 10000 # m2 menjadi hektare (CRS harus berupa meter)
baris.append((nama, round(luas_ha, 2)))
print(nama, round(luas_ha, 2), "ha")Bagian Python murni: for, print, round. Bagian yang diterjemahkan: cara membaca baris dan cara mendapat luas. getFeatures() menjadi kursor, fitur["NAMA_KPH"] menjadi isian kursor, dan fitur.geometry().area() menjadi kolom "SHAPE@AREA". Padanan ArcPy-nya ada di Skrip 31.1, baris 18 sampai 20:
with arcpy.da.SearchCursor(batas, ["NAMA_KPH", "SHAPE@AREA"]) as kursor:
for nama, luas in kursor:
print(nama, round(luas / 10000, 2), "ha") # luas dalam satuan peta (m2) dibagi 10.000Dua baris PyQGIS tidak punya baris kembaran. Baris nama = fitur["NAMA_KPH"] tidak perlu, sebab kursor sudah menaruh nama langsung ke penampung nama. Baris baris.append(...) hanya dipakai skrip QGIS untuk menulis CSV nanti. Angka acuan untuk menguji terjemahan: luas KPH Alpha 4,0 hektare.
Contoh terjemahan 2: penyangga sungai #
Bagian ini dari skrip PyQGIS b2_02_rantai_vektor.py, baris 14 sampai 16:
sempadan = processing.run("native:buffer", {
"INPUT": sungai, "DISTANCE": 30, "SEGMENTS": 8, "END_CAP_STYLE": 0, "JOIN_STYLE": 0,
"MITER_LIMIT": 2, "DISSOLVE": True, "OUTPUT": "TEMPORARY_OUTPUT"})["OUTPUT"]Semua alat QGIS memakai kamus parameter. Padanan ArcPy-nya di Skrip 31.2, baris 14:
arcpy.analysis.Buffer("Sungai.shp", r"memory\sempadan", "30 Meters", dissolve_option="ALL")Empat parameter QGIS tidak muncul di versi ArcPy: SEGMENTS, END_CAP_STYLE, JOIN_STYLE, dan MITER_LIMIT. Artinya versi ArcPy memakai nilai bawaan alat untuk hal-hal itu. Dokumentasi Esri menyebut parameter pilihan line_side dan line_end_type pada Buffer bernilai bawaan FULL dan ROUND. Karena pengaturan ujung dan sambungan tidak sama persis, sempadan di dua alat bisa selisih sedikit di desimal terakhir. Itu bukan galat. [CEK]
Contoh terjemahan 3: dari ArcGIS Pro ke ArcMap #
Terjemahan Pro ke ArcMap lebih mekanis. Ia hanya soal lapis pertama dan kedua. Ambil dua baris dari Skrip 31.2. Versi Pro, baris 15:
arcpy.analysis.Intersect(["Batas_KPH.shp", r"memory\sempadan"], r"memory\irisan")Versi ArcMap, baris 16:
arcpy.Intersect_analysis(["Batas_KPH.shp", r"in_memory\sempadan"], r"in_memory\irisan")Dua penggantian: arcpy.analysis.Intersect(...) menjadi arcpy.Intersect_analysis(...), dan memory\ menjadi in_memory\. Pelajari polanya: nama kotak alat pindah ke belakang dan disambung dengan garis bawah.
Jebakan lintas alat #
Hal-hal ini tidak muncul bila Anda hanya memakai satu alat. Baru terasa ketika Anda berpindah.
| Jebakan | Yang terjadi | Cara aman |
|---|---|---|
| Urutan kolom di kursor | Isian dibaca menurut urutan daftar kolom. Menukar urutan daftar tanpa menukar nama penampung membuat nilai tertukar diam-diam. | Tulis daftar kolom dan nama penampung berdampingan, dan cetak satu baris untuk memeriksa. |
| Jarak dan satuan | QGIS mengikuti satuan sistem koordinat layer. ArcPy membaca satuan dari teks "30 Meters". | Periksa sistem koordinat data, dan tulis satuan di ArcPy. |
| Hasil raster | Hasil native:rastercalc berupa teks jalur. Hasil operasi raster ArcPy berupa objek raster yang harus .save(). | Ingat: satu bungkus jadi layer, satu lagi disimpan dengan .save(). |
| Kutip dalam klausa pilih | QGIS: '"NAMA_KPH" = \'%s\''. Pro: "NAMA_KPH = '%s'". ArcMap: "\"NAMA_KPH\" = '%s'". | Uji klausa dengan satu data kecil dulu. [CEK] |
| Nama kolom bawaan | Daftar kolom Shapefile di ArcPy memuat kolom bantu seperti FID dan Shape, sedangkan GeoPackage di QGIS memuat fid. | Jangan mengandalkan urutan atau jumlah kolom. Sebut nama kolom. [CEK] |
| Angka antaralat | Dua alat bisa beda di desimal terakhir. Di skrip PyQGIS, persen sempadan KPH Beta tercetak 34.6, sedangkan hitungan dengan OGR memberi 34.7. | Bandingkan dengan toleransi, bukan dengan tanda ==. |
| Ekstensi ArcGIS | Alat raster seperti ZonalStatisticsAsTable perlu ekstensi Spatial Analyst atau Image Analyst. QGIS tidak memakai ekstensi berbayar untuk itu. | Cek lisensi sebelum menyerahkan skrip ke orang lain. |
| Tempat menjalankan | Skrip PyQGIS jalan di Windows, macOS, dan Ubuntu. Skrip ArcPy hanya di Windows. Kata "CURRENT" hanya berarti di dalam aplikasi ArcGIS. | Putuskan lebih dulu di komputer mana skrip akan dipakai. |
Satu contoh nyata untuk baris pertama. Anggap Anda menulis kursor dengan urutan ["SHAPE@AREA", "NAMA_KPH"], tetapi tetap membuka dengan for nama, luas in kursor:. Penampung nama kini berisi luas, dan luas berisi nama. Baris round(luas / 10000, 2) gagal dengan TypeError: unsupported operand type(s) for /: 'str' and 'int'. Pesan itu sudah diuji pada pasangan nilai yang dibalik, di Python 3.
Latihan menerjemahkan #
Kerjakan di kertas atau di berkas teks. Tidak ada yang perlu dijalankan di ArcGIS. Jawaban memakai skrip yang sudah ada di buku ini.
- PyQGIS ke ArcPy. Terjemahkan dua baris PyQGIS ini ke ArcGIS Pro:
print("Jumlah fitur:", layer.featureCount())danprint("Nama field:", [f.name() for f in layer.fields()]). Anggap data bernamabatasdi folder kerja. - ArcPy ke PyQGIS. Terjemahkan satu baris ArcPy Pro ini ke PyQGIS:
arcpy.analysis.Select(batas, r"memory\satu_kph", "NAMA_KPH = '%s'" % nama). - Pro ke ArcMap. Terjemahkan dua baris ArcGIS Pro ini ke ArcMap 10.8:
for i, nama in enumerate(daftar, start=1):danprint(f"{i}/{total} selesai: {nama}"). - Menyusun sendiri. Tambahkan satu baris ke tabel padanan Anda: pekerjaan "menghitung jumlah fitur" untuk ArcMap. Gunakan Skrip 31.1.
Contoh jawaban.
- Dari Skrip 31.1, baris 14 dan 15:
print("Jumlah fitur:", int(arcpy.management.GetCount(batas)[0]))
print("Field:", [f.name for f in arcpy.ListFields(batas)])- Dari skrip PyQGIS
b3_02_batch_per_kph.py, baris 24 sampai 26:
satu_kph = processing.run("native:extractbyexpression", {
"INPUT": batas, "EXPRESSION": '"NAMA_KPH" = \'%s\'' % nama,
"OUTPUT": "TEMPORARY_OUTPUT"})["OUTPUT"]- Dari skrip M1 versi ArcMap, baris 20 dan 26 (nomor baris ArcMap bergeser satu karena baris
from __future__):
for i, nama in enumerate(daftar, 1): print("{}/{} selesai: {}".format(i, total, nama))- Dari Skrip 31.1 versi ArcMap, baris 15:
int(arcpy.GetCount_management(batas).getOutput(0)). Di Pro, penulisannyaint(arcpy.management.GetCount(batas)[0]).
Semua jawaban disalin langsung dari berkas sumbernya. Hasil menjalankannya di ArcGIS belum teruji. [CEK]
Cek paham #
- Sebutkan tiga lapis beda saat menerjemahkan skrip QGIS ke ArcPy ArcMap.
- Mengapa
r.width()di PyQGIS menjadir.widthdi ArcPy? - Mengapa sempadan di dua alat bisa selisih di desimal terakhir?
- Mengapa hasil alat QGIS diambil dengan
["OUTPUT"], sedangkan di ArcPy tidak?
Jawaban.
- Gaya Python (Pro lawan ArcMap), nama alat (QGIS lawan ArcPy), dan cara menunjuk data (layer dalam proyek lawan jalur teks).
- Di PyQGIS, lebar raster adalah fungsi, jadi dipanggil dengan kurung. Di ArcPy, ia sifat objek raster, jadi ditulis tanpa kurung.
- Parameter ujung dan sambungan penyangga tidak persis sama. Itu wajar, dan bukan galat.
- Alat QGIS mengembalikan kamus berisi semua keluaran. Alat ArcPy menulis ke nama keluaran yang Anda tentukan sendiri, jadi Anda memakai nama itu langsung.
Kesalahan umum #
- Menerjemahkan seluruh skrip sekaligus. Hasilnya sulit diperiksa. Perbaikan: terjemahkan satu tahap, uji dengan angka acuan, lalu lanjut.
- Menyalin nama alat dari ingatan. Nama dan urutan isian alat bisa keliru. Perbaikan: cek dokumentasi alat.
- Lupa mengganti cara menunjuk data. Di ArcPy, layer tidak "terbuka" di proyek. Perbaikan: tentukan folder kerja dan nama keluaran.
- Menganggap angka dua alat harus persis sama. Perbaikan: bandingkan dengan toleransi kecil.
Ringkasan dan latihan #
- Menerjemahkan skrip berarti menerjemahkan tiga lapis: gaya Python, nama alat, dan cara menunjuk data.
- Python murni (
for,if, kamus, daftar) dipindahkan tanpa diubah. - Tabel padanan membantu mencari nama alat. Dokumentasi alat membantu memeriksa urutan isian.
- Enam langkah: baca pola, tandai Python murni, cari padanan, ganti cara menunjuk data, sesuaikan gaya Python, uji dengan angka acuan.
- Semua skrip ArcPy di buku ini belum dijalankan di ArcGIS dan bertanda [CEK].
Latihan. Ambil skrip PyQGIS dari Bab 21 yang menghitung NDVI per KPH. Tulis ulang rencana terjemahannya ke ArcPy dengan enam langkah di atas, tanpa menjalankan apa pun. Mana yang paling banyak berubah: bagian Python murni, nama alat, atau cara menunjuk data?
Tabel perbandingan: tiga lapis beda #
| Lapis | Yang berbeda | Contoh |
|---|---|---|
| Gaya Python | Pro lawan ArcMap | print(nama, luas) lawan print("%s %s" % (nama, luas)) |
| Nama alat | QGIS lawan ArcPy | native:buffer lawan arcpy.analysis.Buffer |
| Cara menunjuk data | layer dalam proyek lawan jalur teks | QgsVectorLayer(...) lawan "Batas_KPH.shp" |