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/1160.png
  1. 接着 QGIS 中就可以看到 ne_10m_airports 图层。

../_images/2122.png
  1. 使用 识别图征 按钮,选择任一个点看一下有哪些属性。你会发现机场的名字是记在 name 属性,而机场的 3 位英文代码则是记在 iata_code 属性。

../_images/364.png
  1. QGIS 有内建终端机模式,可以让你输入 Python 指令和查阅输出,对于学习和快速的资料处理很有帮助。选择 附加元件 ‣ Python 主控台,就可以进入该模式。

../_images/444.png
  1. 这时有个新面板会出现在 QGIS 画布下方,而且最底下会有一个左侧有 >>> 的栏位,这里就是输入指令的地方。在此模式下方所有与 QGIS 环境的互动,都会透过一个叫做 iface 的变数来达成。例如要存取现在显示在 QGIS 中的图层的话,可输入如下指令后按下 Enter 键,layer 这个变数就会被设定成此图层。

layer = iface.activeLayer()
../_images/544.png
  1. Python 中有个蛮实用的函数叫做 dir(),它会秀出某物件的所有可操作方法。当你不太了解这个物件该怎么操作时,这个函数相当管用。所以我们就输入如下指令,看看接下来我们可以对 layer 变数做什么事情。

dir(layer)
../_images/642.png
  1. 这下子你就会看到一长串的可用函数。在这里,我们试着用 getFeatures(),这是帮助取得某个在图层中的图征的函数,在我们的例子中,它可以帮我们取得图层中代表「机场」的点。使用下面的指令就可以逐一取得图层中的所有图征,不过记得一定要在第二行的最前面加上 2 个空格。

for f in layer.getFeatures():
  print f
../_images/742.png
  1. 接着在输出画面中就可以看到每一行都是图层中的一个特定图征。图征的资讯会存在 f 变数当中,所以只要对 f 进行一些操作,就可以取得图征的属性,像是输入下面的指令,就可以印出每个机场的 nameiata_code 属性。

for f in layer.getFeatures():
  print f['name'], f['iata_code']
../_images/841.png
  1. 现在我们已经知道要怎么用指令取得图层中的图征属性了,接下来我们还得取得图征的座标。向量图征的座标可以使用一个叫做 geometry() 的函数来取得,此函数会输出一种「几何物件」,这里我们把它存在 geom 变数中,而「点几何物件」可以透过 asPoint() 函数来取得这个物件的 x 与 y 座标。如果图征是线或是多边形的话,取得座标的函数会变成 asPolyline()asPolygon()。请输入以下指令后按下 Enter,就可以看到每个图征的座标。

for f in layer.getFeatures():
  geom = f.geometry()
  print geom.asPoint()
../_images/941.png
  1. 如果我们只想要秀出 x 座标的话要怎么办? 只要在点几何物件上多套入一个 x() 函数就行了,如下所示。

for f in layer.getFeatures():
  geom = f.geometry()
  print geom.asPoint().x()
../_images/1039.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/1161.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/1240.png
  1. 最后就可以在输出的文字档中,查看我们刚刚利用 Python 指令从 shapefile 中转存出来的资料了!

../_images/1339.png