Python 程式設計的初步上手

警告

本教學已有新的版本,請前往 Python 程式設計的初步上手 (QGIS3)

QGIS 具有強大的程式設計介面,支援目前流行的 Python 語言,可以讓你擴展此軟體的核心功能,或是撰寫腳本讓你想做的事情可以自動執行。不論你是否對 QGIS 或 Python 有深入了解,知道一點 QGIS 程式介面的使用方法一定會讓你的工作事半功倍。閱讀本教學不需任何程式設計的背景,我們會從頭開始敘述 QGIS 的 Python 程式設計方法 (PyQGIS)。

內容說明

我們要以 Python 腳本處理世界上所有機場位置的點向量圖層,此腳本會輸出圖層中機場名字、機場代碼與經緯度資訊到一個文字檔中。

取得資料

本教學使用 Natural Earth 提供的 機場 資料集。

下載 機場 shapefile

資料來源 [NATURALEARTH]

操作流程

  1. 在 QGIS 中選擇 圖層 ‣ 加入向量圖層,找到剛下載的 ne_10m_airports.zip 檔案,按下 開啟,選擇 ne_10m_airports.shp,最後按 確定

../_images/1185.png
  1. 接著 QGIS 中就可以看到 ne_10m_airports 圖層。

../_images/2151.png
  1. 使用 識別圖徵 按鈕,選擇任一個點看一下有哪些屬性。你會發現機場的名字是記在 name 屬性,而機場的 3 位英文代碼則是記在 iata_code 屬性。

../_images/394.png
  1. QGIS 有內建終端機模式,可以讓你輸入 Python 指令和查閱輸出,對於學習和快速的資料處理很有幫助。選擇 附加元件 ‣ Python 主控台,就可以進入該模式。

../_images/458.png
  1. 這時有個新面板會出現在 QGIS 畫布下方,而且最底下會有一個左側有 >>> 的欄位,這裡就是輸入指令的地方。在此模式下方所有與 QGIS 環境的互動,都會透過一個叫做 iface 的變數來達成。例如要存取現在顯示在 QGIS 中的圖層的話,可輸入如下指令後按下 Enter 鍵,layer 這個變數就會被設定成此圖層。

layer = iface.activeLayer()
../_images/551.png
  1. Python 中有個蠻實用的函數叫做 dir(),它會秀出某物件的所有可操作方法。當你不太了解這個物件該怎麼操作時,這個函數相當管用。所以我們就輸入如下指令,看看接下來我們可以對 layer 變數做什麼事情。

dir(layer)
../_images/649.png
  1. 這下子你就會看到一長串的可用函數。在這裡,我們試著用 getFeatures(),這是幫助取得某個在圖層中的圖徵的函數,在我們的例子中,它可以幫我們取得圖層中代表「機場」的點。使用下面的指令就可以逐一取得圖層中的所有圖徵,不過記得一定要在第二行的最前面加上 2 個空格。

for f in layer.getFeatures():
  print f
../_images/749.png
  1. 接著在輸出畫面中就可以看到每一行都是圖層中的一個特定圖徵。圖徵的資訊會存在 f 變數當中,所以只要對 f 進行一些操作,就可以取得圖徵的屬性,像是輸入下面的指令,就可以印出每個機場的 nameiata_code 屬性。

for f in layer.getFeatures():
  print f['name'], f['iata_code']
../_images/848.png
  1. 現在我們已經知道要怎麼用指令取得圖層中的圖徵屬性了,接下來我們還得取得圖徵的座標。向量圖徵的座標可以使用一個叫做 geometry() 的函數來取得,此函數會輸出一種「幾何物件」,這裡我們把它存在 geom 變數中,而「點幾何物件」可以透過 asPoint() 函數來取得這個物件的 x 與 y 座標。如果圖徵是線或是多邊形的話,取得座標的函數會變成 asPolyline()asPolygon()。請輸入以下指令後按下 Enter,就可以看到每個圖徵的座標。

for f in layer.getFeatures():
  geom = f.geometry()
  print geom.asPoint()
../_images/948.png
  1. 如果我們只想要秀出 x 座標的話要怎麼辦? 只要在點幾何物件上多套入一個 x() 函數就行了,如下所示。

for f in layer.getFeatures():
  geom = f.geometry()
  print geom.asPoint().x()
../_images/1055.png
  1. 以上所講的各種操作,只要把它們拼湊起來,就可以產生我們想要的輸出結果。像是底下的程式碼可以印出每個機場的名字、iata_code 以及經緯度,程式碼中的 %s%f 是用來調整字串和數字的輸出格式的記號。

for f in layer.getFeatures():
  geom = f.geometry()
  print '%s, %s, %f, %f' % (f['name'], f['iata_code'],
         geom.asPoint().y(), geom.asPoint().x())
../_images/1186.png
  1. 到目前為止,所有的輸出都直接顯示在螢幕上,但其實如果能夠存成檔案,應該會更好用。你可以輸入如下的程式碼,第一行的檔名和路徑記得改成你想存在你電腦中的樣子,剛才的結果就會另存成新檔。注意我們在每行的結尾都加上了 \n,這是用來告訴電腦存完每個圖徵資料後應該要換到下一行繼續存。另外,unicode_line = line.encode('utf-8') 這一行的用意在於,有些圖徵的屬性使用了 Unicode 字元,我們要先把它們編碼成 UTF-8 格式,才能正確地存到文字檔當中。

output_file = open('c:/Users/Ujaval/Desktop/airports.txt', 'w')
for f in layer.getFeatures():
  geom = f.geometry()
  line = '%s, %s, %f, %f\n' % (f['name'], f['iata_code'],
          geom.asPoint().y(), geom.asPoint().x())
  unicode_line = line.encode('utf-8')
  output_file.write(unicode_line)
output_file.close()
../_images/1257.png
  1. 最後就可以在輸出的文字檔中,查看我們剛剛利用 Python 指令從 shapefile 中轉存出來的資料了!

../_images/1355.png

If you want to give feedback or share your experience with this tutorial, please comment below. (requires GitHub account)