arcgis python实例_ArcGIS Python编程案例(14)-五个常用Python处理任务
我們將在本章介紹以下案例:
從分隔符文本文件中讀取數(shù)據(jù)
發(fā)送電子郵件
訪問(wèn)FTP服務(wù)器中的文件
創(chuàng)建ZIP文件
讀取XML文件
引言
在本章中,你將學(xué)習(xí)如何編寫(xiě)Python腳本來(lái)執(zhí)行常用的處理任務(wù)。這些任務(wù)包括讀寫(xiě)分隔符文本文件,發(fā)送電子郵件,與FTP服務(wù)器交互操作,創(chuàng)建.zip文件以及讀寫(xiě)JSON和XML文件。GIS程序員應(yīng)當(dāng)了解如何在Python腳本來(lái)完成這些功能。
從分隔符文本文件中讀取數(shù)據(jù)
對(duì)于GIS程序員來(lái)說(shuō)使用Python處理文件是非常重要的環(huán)節(jié)。文本文件經(jīng)常作為不同系統(tǒng)之間的數(shù)據(jù)交換格式。文本文件簡(jiǎn)單,跨平臺(tái)并且易于處理。逗號(hào)分隔符文本文件和制表符分隔符文本文件是最為常用的形式。對(duì)于GIS程序員來(lái)說(shuō)讀取包含X,Y坐標(biāo)以及其他屬性信息的逗號(hào)分隔符文本文件是一類(lèi)常見(jiàn)的處理任務(wù)。這些讀取后信息再轉(zhuǎn)換成像shapefile或地理數(shù)據(jù)庫(kù)的GIS數(shù)據(jù)格式。
Getting ready
使用Python的文件處理功能前,你必須首先打開(kāi)文件。文件打開(kāi)后,文件中的數(shù)據(jù)就可以通過(guò)Python提供的功能進(jìn)行處理,最后關(guān)閉文件。處理完成后要記得關(guān)閉文件。
在本案例中,你將學(xué)習(xí)如何對(duì)一個(gè)逗號(hào)分隔符文本文件執(zhí)行打開(kāi),讀取,處理并關(guān)閉操作。
How to do it...
按照以下步驟創(chuàng)建Python腳本來(lái)讀取逗號(hào)分隔符文本文件:
1.在C:\ArcpyBook\data文件夾中找到一個(gè)N_America.A2007275.txt的文件。用文本編輯器打開(kāi)該文件,你會(huì)看到如下內(nèi)容:
18.102,-94.353,310.7,1.3,1.1,10/02/2007,0420,T,72
19.300,-89.925,313.6,1.1,1.0,10/02/2007,0420,T,82
19.310,-89.927,309.9,1.1,1.0,10/02/2007,0420,T,68
26.888,-101.421,307.3,2.7,1.6,10/02/2007,0425,T,53
26.879,-101.425,306.4,2.7,1.6,10/02/2007,0425,T,45
36.915,-97.132,342.4,1.0,1.0,10/02/2007,0425,T,100
................
該文件包含的火情數(shù)據(jù)是從2007年10月02日當(dāng)天衛(wèi)星遙感影像判斷獲取。每行數(shù)據(jù)包含了經(jīng)緯度信息以及其他相關(guān)信息,比如日期和時(shí)間,衛(wèi)星類(lèi)型,可信度等等。在本案例中,你將提取出緯度,經(jīng)度和可信度信息。
2.打開(kāi)IDLE,創(chuàng)建一個(gè)腳本文件并保存為
C:\ArcpyBook\Appendix2\ReadDelimitedTextFile.py文件。
3.調(diào)用Pyhon的open()函數(shù)來(lái)打開(kāi)要讀取的文件:
f = open("C:/ArcpyBook/data/N_America.A2007275.txt","r")
4.讀取文本文件中的內(nèi)容并寫(xiě)入到列表中:
lstFires = f.readlines()
5.添加一個(gè)for循環(huán)語(yǔ)句來(lái)迭代遍歷lstFires變量中的所有行:
for fire in lstFires:
6.調(diào)用split()函數(shù)并使用逗號(hào)作為分隔符,將分離后的值保存到列表中,然后賦值給變量lstValues。保證語(yǔ)句的縮進(jìn)使其位于for語(yǔ)句中:
lstValues = fire.split(",")
7.使用索引值來(lái)獲取緯度,經(jīng)度和可信度,并分別創(chuàng)建新的變量:
latitude = float(lstValues[0])
longitude = float(lstValues[1])
confid = int(lstValues[8])
8.使用print語(yǔ)句打印所有值:
print "The latitude is: " + str(latitude) + " The longtitude is " + str(longtitude) + "The confidence value is " + str(confid)
9.關(guān)閉文件:
f.close()
10.完整代碼如下:
f = open("C:/ArcpyBook/data/N_America.A2007275.txt","r")
lstFires = f.readlines()
for fire in lstFires:
lstValues = fire.split(",")
latitude = float(lstValues[0])
longitude = float(lstValues[1])
confid = int(lstValues[8])
print "The latitude is: " + str(latitude) + " The longtitude is " + str(longtitude) + "The confidence value is " + str(confid)
f.close()
11.保存并運(yùn)行腳本。你將看到如下結(jié)果顯示:
The latitude is: 18.102 The longitude is: -94.353 The confidence value is: 72
The latitude is: 19.3 The longitude is: -89.925 The confidence value is: 82
The latitude is: 19.31 The longitude is: -89.927 The confidence value is: 68
The latitude is: 26.888 The longitude is: -101.421 The confidence value is: 53
The latitude is: 26.879 The longitude is: -101.425 The confidence value is: 45
The latitude is: 36.915 The longitude is: -97.132 The confidence value is: 100
...................
The latitude is: 54.19 The longitude is: -122.502 The confidence value is: 92
How it works...
Python中open()函數(shù)創(chuàng)建一個(gè)文件對(duì)象,該對(duì)象引用一個(gè)鏈接地址來(lái)指向計(jì)算機(jī)中的文件。open()函數(shù)中的第一個(gè)參數(shù)是你想要打開(kāi)文件的路徑。第二個(gè)參數(shù)指定一種模式,該模式通常是只讀(r),寫(xiě)入(w)或添加(a)。r模式表明你打開(kāi)文件進(jìn)行只讀操作,而w模式則表明你打開(kāi)文件要進(jìn)行寫(xiě)入操作。如果你以寫(xiě)入模式打開(kāi)的文件已存在,那么Python就會(huì)覆蓋掉該文件中已有數(shù)據(jù),因此使用該模式應(yīng)當(dāng)注意。添加模式(a)則會(huì)打開(kāi)文件進(jìn)行寫(xiě)入操作,但是不會(huì)覆蓋已有數(shù)據(jù),而是在文件末尾添加寫(xiě)入的數(shù)據(jù)。在本案例中,我們以只讀模式打開(kāi)N_America.A2007275.txt文件。
readlines()函數(shù)會(huì)讀取整個(gè)文件內(nèi)容并寫(xiě)入一個(gè)Python列表中。該列表保存到變量lstFires。文本文件中的每一行數(shù)據(jù)是列表中的一個(gè)元素。由于該函數(shù)會(huì)讀取整個(gè)文件到列表中,因此調(diào)用該方法時(shí)需要注意,一個(gè)大文件會(huì)顯著影響性能。
for循環(huán)語(yǔ)句用于迭代遍歷lstFires中的每一個(gè)值,在該語(yǔ)句中的split()函數(shù)用于從以某種分隔符分隔文本行中創(chuàng)建一個(gè)列表對(duì)象。本案例中的文件是以逗號(hào)作為分隔符,因此我們可以調(diào)用split(",")語(yǔ)句。你還可以使用其他像制表符,空格或其他分隔符來(lái)分割文本。split()函數(shù)創(chuàng)建的列表對(duì)象保存在lstValues變量中。該變量包含了每一個(gè)火情數(shù)據(jù)。如下圖所示。你會(huì)看到緯度數(shù)據(jù)占據(jù)第一個(gè)位置,經(jīng)度數(shù)據(jù)占據(jù)第二個(gè)數(shù)據(jù)。列表從零值開(kāi)始索引:
使用索引值(分別引用緯度,經(jīng)度和可信度),我們創(chuàng)建了latitude,longitude以及confid三個(gè)新變量。最后,我們打印輸出每一個(gè)值。我們可以調(diào)用插入游標(biāo)(InsertCursor)對(duì)象將這些信息寫(xiě)入到一個(gè)要素類(lèi)中。
There's more...
同讀取文件一樣,你還可以向文件中寫(xiě)入數(shù)據(jù)。write()函數(shù)可用于將列表結(jié)構(gòu)的內(nèi)容寫(xiě)入到一個(gè)文件中。寫(xiě)入數(shù)據(jù)之前,你需要先以寫(xiě)入或添加模式打開(kāi)文件。
發(fā)送電子郵件
有時(shí)候,你可能需要編寫(xiě)Python腳本來(lái)發(fā)送電子郵件。舉個(gè)例子,在一個(gè)長(zhǎng)時(shí)間運(yùn)行的地理處理操作中需要提醒操作成功完成或出現(xiàn)錯(cuò)誤,在類(lèi)似情況下,發(fā)送電子郵件就很有用處。
Getting ready
通過(guò)Python腳本發(fā)送電子郵件需要腳本運(yùn)行的機(jī)器能夠訪問(wèn)郵箱服務(wù)器,可以是一個(gè)Yahoo,Gmail之類(lèi)的公共的電子郵件服務(wù),這也可以使用像Outlook的應(yīng)用程序配置的發(fā)送郵件服務(wù)器。不論哪種方式,你都需要知道電子郵箱服務(wù)器的域名和端口。Python的smtplib模塊用于創(chuàng)建郵箱服務(wù)器的連接并發(fā)送電子郵件。
Python的email模塊包含一個(gè)Message類(lèi)用來(lái)表達(dá)電子郵件信息。每一條消息包含消息頭和消息體。該類(lèi)不能用于發(fā)送電子郵件,只是處理消息對(duì)象的表達(dá)。Message類(lèi)通過(guò)調(diào)用message_from_file()和message_from_string()函數(shù)分別解析包含在電子郵件中的文件和字符串。兩個(gè)函數(shù)都會(huì)創(chuàng)建一個(gè)新的Message對(duì)象。郵件體可以通過(guò)調(diào)用Message.get_payload()方法獲取。
在本案例中,你將學(xué)習(xí)如何在Python腳本中使用smtp類(lèi)來(lái)發(fā)送包含附件內(nèi)容的電子郵件。
原書(shū)采用Gmail郵箱服務(wù),由于網(wǎng)絡(luò)原因,我們?cè)诎咐懈臑槭褂镁W(wǎng)易126郵箱服務(wù)。如果你已經(jīng)擁有了一個(gè)126賬號(hào),那么只要提供你的用戶(hù)名和密碼就可以。如果你還沒(méi)有126賬號(hào),你需要注冊(cè)一個(gè)或者使用其他郵件服務(wù)來(lái)完成本練習(xí);126郵箱賬號(hào)是免費(fèi)的。
How to do it...
按照以下步驟來(lái)創(chuàng)建能夠發(fā)送電子郵件的腳本:
1.打開(kāi)IDLE,創(chuàng)建一個(gè)腳本并保存為C:\ArcpyBook\Appendix2\SendEmail.py。
2.為了能夠在發(fā)送帶附件的電子郵件,你需要導(dǎo)入os模塊,smtplib模塊以及email模塊中多個(gè)類(lèi)。如下所示:
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os
3.創(chuàng)建下面的幾個(gè)變量并分別保存你的Gmail用戶(hù)名和密碼。
##<用戶(hù)名>替換為你的郵箱賬號(hào)
gmail_user = "<用戶(hù)名>"
##<密碼>替換為你的郵箱賬號(hào)密碼
gmail_pwd= "<密碼>"
4.定義一個(gè)mail()函數(shù)。該函數(shù)將接受四個(gè)參數(shù):to,subject,text以及attach。每一個(gè)參數(shù)的意義不言而喻。創(chuàng)建一個(gè)新的MIMEMultipart對(duì)象并分別賦值給from,to和subject鍵值。你還可以對(duì)新創(chuàng)建的對(duì)象調(diào)用MIMEMultipart.attach()方法來(lái)給郵件添加一個(gè)文本附件:
def mail(to,subject,text,attach):
msg = MIMEMultipart()
msg['From'] = gmail_user
msg['To'] = to
msg['Subject'] = subject
msg.attach(MIMEText(text))
5.在郵件中添加附件:
part = MIMEBase("application","octet-stream")
part.set_payload(open(attach,"rb").read())
Encoders.encode_base64(part)
part.add_header("Content-Dispositon","attachment;filename='%s'" % os.path.basename(attach))
msg.attach(part)
6.創(chuàng)建一個(gè)新的SMTP對(duì)象引用谷歌Gamil服務(wù),傳遞用戶(hù)名和密碼來(lái)連接該郵件服務(wù),發(fā)送郵件最后關(guān)閉連接:
mailServer = smtplib.SMTP("smtp.126.com")
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user,gmail_pwd)
mailServer.sendmail(gmail_user,to,msg.as_string())
mailServer.quit()
7.調(diào)用mail()函數(shù),傳遞收件人,郵件主題,郵件的內(nèi)容以及附件參數(shù):
##<收件人地址>替換為發(fā)件人郵箱地址
mail("<收件人地址>","Hello from python!","This is an email sent with python","C:/ArcpyBook/data/bc_pop1996.csv")
8.完整代碼如下:
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os
##<用戶(hù)名>替換為你的郵箱賬號(hào)
gmail_user = "<用戶(hù)名>"
##<密碼>替換為你的郵箱賬號(hào)密碼
gmail_pwd= "<密碼>"
def mail(to,subject,text,attach):
msg = MIMEMultipart()
msg['From'] = gmail_user
msg['To'] = to
msg['Subject'] = subject
msg.attach(MIMEText(text))
part = MIMEBase("application","octet-stream")
part.set_payload(open(attach,"rb").read())
Encoders.encode_base64(part)
part.add_header("Content-Disposition","attachment;filename='%s'" % os.path.basename(attach))
msg.attach(part)
mailServer = smtplib.SMTP("smtp.126.com")
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user,gmail_pwd)
mailServer.sendmail(gmail_user,to,msg.as_string())
mailServer.quit()
print "Send Successfully!"
##<收件人地址>替換為發(fā)件人郵箱地址
mail("<收件人地址>","Hello from python!","This is an email sent with python","C:/ArcpyBook/data/bc_pop1996.csv")
9.保存并運(yùn)行腳本。指定某個(gè)郵箱賬號(hào)作為收件人。
How it works...
mail()函數(shù)接受的第一個(gè)參數(shù)是接收郵件的電子郵箱地址。該地址可以是任何合法的電子郵箱地址,不過(guò)需要提供一個(gè)可以查看的郵箱賬號(hào),這樣你才可以確認(rèn)腳本是否正確執(zhí)行。第二個(gè)參數(shù)是郵件的主題。第三個(gè)參數(shù)是郵件內(nèi)容。最后一個(gè)參數(shù)是附件的名稱(chēng)。在這里將bc_pop1996.csv文件作為附件。你還可以使用任何你能夠獲取的文件。
隨后我們?cè)趍ail()函數(shù)中創(chuàng)建了一個(gè)新的MIMEMultipart對(duì)象,并分別賦給from,to和subject鍵值。你還可以調(diào)用MIMEMultipart.attach()方法將郵件內(nèi)容附加到msg對(duì)象中。隨后通過(guò)調(diào)用msg.attach(part)語(yǔ)句將bc_pop1996.csv文件作為附件添加到使用MIMEBase對(duì)象創(chuàng)建的郵件中。
到目前為止,我們已經(jīng)了解了如何發(fā)送一個(gè)簡(jiǎn)單的電子郵件。但是,我們需要發(fā)送一個(gè)包含文本和附件的更為復(fù)雜的電子郵件。這就需要使用MIME消息,該消息提供處理多用途電子郵件的功能。MIME消息需要不同部分的邊界以及額外的頭信息來(lái)指定要發(fā)送的內(nèi)容。MIMEBase類(lèi)是一個(gè)Message的抽象子類(lèi)并且能夠發(fā)送多部分類(lèi)型的郵件。由于這是一個(gè)抽象子類(lèi),因此你不能創(chuàng)建真正意義的實(shí)例。不過(guò)你可以使用其中的一個(gè)子類(lèi),比如MIMEText來(lái)實(shí)現(xiàn)。mail()函數(shù)中的最后一步創(chuàng)建一個(gè)新的SMTP對(duì)象來(lái)指向126郵件服務(wù),傳遞用戶(hù)名和密碼來(lái)連接該郵件服務(wù),發(fā)送郵件最后關(guān)閉連接。
訪問(wèn)FTP服務(wù)器中的文件
對(duì)于GIS程序員來(lái)說(shuō)獲取FTP服務(wù)器中的文件進(jìn)行處理也是非常普遍的操作,并且這類(lèi)操作頁(yè)可以利用Python腳本來(lái)實(shí)現(xiàn)自動(dòng)化處理。
Getting ready
通過(guò)ftplib模塊可以完成連接FTP服務(wù)器并下載文件操作。FTP對(duì)象接受一個(gè)主機(jī)名稱(chēng),一個(gè)用戶(hù)名以及密碼參數(shù)來(lái)創(chuàng)建一個(gè)與FTP服務(wù)器的連接。連接打開(kāi)之后,你就可以查找并下載文件了。
在本案例中,你將連接到NASA的某FTP站點(diǎn)下載一副TIF格式的圖像。
How to do it...
按照以下步驟創(chuàng)建腳本來(lái)連接到一個(gè)FTP服務(wù)器并下載文件:
1.打開(kāi)IDLE,創(chuàng)建一個(gè)腳本并保存為C:\ArcpyBook\Appendix2\ftp.py。
2.我們將要連接到NASA的FTP服務(wù)器。訪問(wèn)網(wǎng)站ftp://is.sci.gsfc.nasa.gov。
3.導(dǎo)入ftplib,os和socket模塊:
import ftplib
import os
import socket
4.添加以下變量分別定義URL地址,目錄和文件名:
HOST = "is.sci.gsfc.nasa.gov"
DIRN= "/testdata/BLUEMARBLE_POSTER_IMAGES/"
FILE = "FLOOD_VNCLR_d20140601_t0612599_e0614240_BEFORE.tif"
5.添加以下語(yǔ)句塊創(chuàng)建一個(gè)連接。如果連接出現(xiàn)錯(cuò)誤會(huì)生成一條錯(cuò)誤消息。如果連接成功則會(huì)顯示一條成功連接的消息:
try:
f = ftplib.FTP(HOST)
except (socket.error,socket.gaierror),e:
print "ERROR: cannot reach '%s'" % HOST
print "*** Connected to host '%s'" % HOST
6.添加以下語(yǔ)句塊來(lái)匿名方式登錄服務(wù)器:
try:
f.login()
except ftplib.error_perm:
print "ERROR: cannot login anonymously"
f.quit()
print "*** Logged in as 'anonymous'"
7.添加以下語(yǔ)句塊將當(dāng)期目錄更新至DIRN變量中指定的目錄:
try:
f.cwd(DIRN)
except ftplib.error_perm:
print "ERROR: cannot CD to '%s'" % DIRN
f.quit()
print "*** Changed to '%s'" % DIRN
8.調(diào)用FTP.retrbinary()函數(shù)獲取數(shù)據(jù)文件:
try:
f.retrbinary("RETR %s" %FILE,open(FILE,'wb').write)
except ftplib.error_perm:
print "ERROR: cannot read file '%s'" % FILE
os.unlink(FILE)
else:
print "*** Downloaded '%s' to CWD" % FILE
9.斷開(kāi)與服務(wù)器的連接:
f.quit()
10.完整代碼如下:
import ftplib
import os
import socket
HOST = "is.sci.gsfc.nasa.gov"
DIRN= "/testdata/BLUEMARBLE_POSTER_IMAGES/"
FILE = "FLOOD_VNCLR_d20140601_t0612599_e0614240_BEFORE.tif"
try:
f = ftplib.FTP(HOST)
print "*** Connected to host '%s'" % HOST
try:
f.login()
print "*** Logged in as 'anonymous'"
try:
f.cwd(DIRN)
print "*** Changed to '%s'" % DIRN
try:
f.retrbinary("RETR %s" %FILE,open(FILE,'wb').write)
except ftplib.error_perm:
print "ERROR: cannot read file '%s'" % FILE
os.unlink(FILE)
else:
print "*** Downloaded '%s' to CWD" % FILE
finally:
f.quit()
except ftplib.error_perm:
print "ERROR: cannot CD to '%s'" % DIRN
f.quit()
except ftplib.error_perm:
print "ERROR: cannot login anonymously"
f.quit()
except (socket.error,socket.gaierror),e:
print "ERROR: cannot reach '%s'" % HOST
11.保存并運(yùn)行腳本。如果一切順利的話,你會(huì)看到如下結(jié)果顯示:
*** Connected to host 'is.sci.gsfc.nasa.gov'
*** Logged in as 'anonymous'
*** Changed to '/testdata/BLUEMARBLE_POSTER_IMAGES/'
*** Downloaded 'FLOOD_VNCLR_d20140601_t0612599_e0614240_BEFORE.tif' to CWD
12.查看C:\ArcpyBook\Appendix2目錄下的文件。默認(rèn)情況下,FTP會(huì)將文件下載到當(dāng)前工作目錄中(同python腳本文件位于同一目錄下):
How it works...
連接FTP服務(wù)器之前,你需要先知道URL地址。你還需要知道要下載文件的文件名和所在目錄。在腳本中,我們已經(jīng)對(duì)這些信息進(jìn)行硬編碼處理,這樣你就可以專(zhuān)注于應(yīng)用FTP相關(guān)的功能。利用這些信息我們隨后會(huì)創(chuàng)建一個(gè)NASA的FTP服務(wù)器的連接。這可以通過(guò)ftplib.FTP()函數(shù)接受一個(gè)URL地址作為主機(jī)參數(shù)來(lái)完成。
is.sci.gsfc.nasa.gov服務(wù)器接受匿名登錄,因此我們采用這樣方式來(lái)連接服務(wù)器。需要注意一點(diǎn),如果服務(wù)器不接受匿名登錄方式,你就需要提供一個(gè)用戶(hù)名和密碼。登錄成功后,隨后會(huì)將當(dāng)前的根目錄地址更改為DIRN變量中定義的目錄。這一步通過(guò)調(diào)用cwd()函數(shù)來(lái)實(shí)現(xiàn)。隨后調(diào)用retrbinary()函數(shù)來(lái)下載kmz文件。最后,你還需要在下載完成后斷開(kāi)與FTP服務(wù)器的連接。這一步可通過(guò)調(diào)用quit()方法完成。
There's more...
你還可以調(diào)用其他與FTP相關(guān)的方法來(lái)執(zhí)行不同的操作。通常來(lái)講,這些方法可分為目錄級(jí)別操作與文件級(jí)別操作。目錄級(jí)別方法包括dir()方法用來(lái)獲取目錄中的文件列表,mkd()方法用來(lái)創(chuàng)建一個(gè)新的目錄,pwd()方法來(lái)獲取當(dāng)前的工作目錄,而cwd()方法則更改當(dāng)前目錄位置。
ftplib模塊還包括與文件操作相關(guān)的方法。你可以上傳或下載二進(jìn)制文件或純文本文件。retrbinary()和storbinary()方法則分別用于獲取和保存文件。純文本文件可以調(diào)用retrlines()和storlines()方法來(lái)獲取和保存。
你還可以關(guān)注FTP類(lèi)中的其他方法。調(diào)用delete()方法可以刪除文件,而rename()方法可以重命名文件。你還可以通過(guò)調(diào)用sendcmd()方法來(lái)向FTP服務(wù)器發(fā)送指令。
創(chuàng)建ZIP文件
GIS日常業(yè)務(wù)中需要將大文件壓縮為.zip格式便于共享。你可以使用Python提供的模塊來(lái)解壓縮.zip格式文件。
Getting ready
Zip格式是一種常用的壓縮歸檔格式,該格式可以使用Python中的zipfile模塊進(jìn)行處理。ZipFile類(lèi)可用于創(chuàng)建,讀取以及寫(xiě)入.zip文件。創(chuàng)建一個(gè)新的.zip文件,你只要提供一個(gè)文件名以及模式參數(shù),比如w模式則表明你想要對(duì)文件寫(xiě)入數(shù)據(jù)。下面的代碼示例中,我們創(chuàng)建一個(gè)叫做dataFile.zip的文件。第二個(gè)參數(shù)w表示會(huì)創(chuàng)建一個(gè)新文件。在寫(xiě)入模式中會(huì)創(chuàng)建一個(gè)新文件或覆蓋帶相同名稱(chēng)的已有文件。一個(gè)可選的壓縮參數(shù)可在創(chuàng)建文件時(shí)使用。該參數(shù)可以設(shè)置為ZIP_STORED或者ZIP_DEFLATED:
zipfile.ZipFile("dataFile.zip","w","ZIP_STORED")
在本案例中,你會(huì)將位于C:\ArcpyBook\data目錄下的所有shapefile文件打包壓縮成一個(gè)zip格式的壓縮文件。
How to do it...
按照以下步驟來(lái)學(xué)習(xí)如何編寫(xiě)腳本來(lái)創(chuàng)建一個(gè).zip文件:
1.打開(kāi)IDLE,創(chuàng)建一個(gè)腳本文件并保存為C:\ArcpyBook\Appendix2\CreateZipfile.py。
2.導(dǎo)入zipfile和os模塊:
import zipfile
import os
3.以寫(xiě)入模式創(chuàng)建一個(gè)新的shapefile.zip文件,并添加一個(gè)壓縮參數(shù):
zfile = zipfile.ZipFile("shapefile.zip","w",zipfile.ZIP_STORED)
4.下一步,我們會(huì)調(diào)用os.listdir()函數(shù)來(lái)創(chuàng)建數(shù)據(jù)目錄中的文件列表:
files = os.listdir("C:/ArcpyBook/data")
5.循環(huán)遍歷了列表中的文件,如果文件擴(kuò)展名為shp,shx或dbf則寫(xiě)入.zip文件中:
for f in files:
if f.endswith("shp") or f.endswith("shx") or f.endswith("dbf"):
zfile.write("C:/ArcpyBook/data/" + f)
6.打印文件列表中所有寫(xiě)入到zip文件中的文件。你可以調(diào)用ZipFile.namelist()函數(shù)來(lái)創(chuàng)建壓縮文件中的文件列表:
for f in zipfile.namelist():
print "Added %s" % f
7.關(guān)閉.zip文件:
zfile.close()
8.完整代碼如下;
import zipfile
import os
zfile = zipfile.ZipFile("shapefile.zip","w",zipfile.ZIP_STORED)
files = os.listdir("C:/ArcpyBook/data")
for f in files:
if f.endwith("shp") or f.endwith("shx") or f.endwith("dbf"):
zfile.write("C:/ArcpyBook/data/" + f)
for f in zfile.namelist():
print "Added %s" % f
zfile.close()
9.保存并運(yùn)行代碼。你會(huì)看到如下結(jié)果顯示:
Added ArcpyBook/data/Burglaries_2009.dbf
Added ArcpyBook/data/Burglaries_2009.shp
Added ArcpyBook/data/Burglaries_2009.shx
Added ArcpyBook/data/Streams.dbf
Added ArcpyBook/data/Streams.shp
Added ArcpyBook/data/Streams.shx
10.在資源管理器中,你可以看到如下圖所示的.zip文件。注意壓縮文件的大小(文件大小視文件夾中滿(mǎn)足條件的文件決定),該文件沒(méi)有進(jìn)行壓縮:
11.現(xiàn)在我們要?jiǎng)?chuàng)建一個(gè)壓縮版本的.zip文件看一看有什么變化。如下所示修改代碼:
zfile = zipfile.ZipFile("shapefile2.zip","w",zipfile.ZIP_DEFLATED)
12.保存后運(yùn)行腳本。
13.查看你剛才創(chuàng)建的shapefile2.zip文件的大小。壓縮后文件變小了:
How it works...
在本案例中,我們以寫(xiě)入模式創(chuàng)建了一個(gè)叫做shapefile.zip的文件。在第一版腳本中,我們沒(méi)有壓縮文件內(nèi)容。第二個(gè)版本中我們?cè)赯ipFile對(duì)象構(gòu)造函數(shù)中使用了DEFLATED參數(shù)來(lái)實(shí)現(xiàn)文件內(nèi)容的壓縮。隨后腳本獲取數(shù)據(jù)目錄中的文件列表并循環(huán)遍歷每一個(gè)文件。隨后通過(guò)調(diào)用write()函數(shù)將擴(kuò)展名為.shp,.shx或.dbf的文件寫(xiě)入到壓縮文件中。最后,壓縮文件中的所有文件名打印輸出到屏幕中。
There's more...
保存在ZIP壓縮文件中的內(nèi)容可以通過(guò)調(diào)用read()方法來(lái)進(jìn)行讀取。首先文件以讀取模式打開(kāi),隨后調(diào)用read()方法并接受一個(gè)表示需要讀取的文件名參數(shù)。文件內(nèi)容之后既可以選擇打印輸出到屏幕上,也可以寫(xiě)入到其他文件中或保存為列表或字典變量中。舉個(gè)例子,readme.zip壓縮文件中包含一個(gè)readme.txt文件,下面的腳本代碼就可以實(shí)現(xiàn)讀取readme.txt文件文本內(nèi)容的功能:
import zipfile
zipFile=zipfile.ZipFile("readme.zip","r")
fcontent=zipFile.read("readme.txt")
print fcontent
zipFile.close()
讀取XML文件
XML文件是一種傳輸數(shù)據(jù)和保存數(shù)據(jù)的格式。由于數(shù)據(jù)是保存在純文本文件中,因此XML文件是不依賴(lài)平臺(tái)的。結(jié)構(gòu)上類(lèi)似于HTML,不過(guò)HTML用于顯示數(shù)據(jù)而XML則是用于數(shù)據(jù)傳輸。XML文件有時(shí)候會(huì)作為不同軟件系統(tǒng)之間的GIS數(shù)據(jù)交換格式。
Getting ready
XML文檔是一個(gè)樹(shù)形結(jié)構(gòu),由根元素,子元素以及元素屬性構(gòu)成。元素通常稱(chēng)作節(jié)點(diǎn)(Node)。所有的XML文件都包含一個(gè)根元素。根元素是所有其他元素或子節(jié)點(diǎn)的父元素。下面的示例代碼則展示了一個(gè)XML文檔結(jié)構(gòu)。不同于HTML文件,XML文件大小寫(xiě)敏感:
....
Python提供了多個(gè)用于處理XML文件的模塊。具體使用哪個(gè)模塊應(yīng)該由所執(zhí)行的操作來(lái)決定。不要試圖使用單個(gè)模塊來(lái)解決所有問(wèn)題。每一個(gè)模塊都有自己擅長(zhǎng)處理的特定功能。在本案例中,你會(huì)學(xué)習(xí)如何使用文檔中的nodes和element屬性來(lái)讀取XML文件中的數(shù)據(jù)。
你可以使用許多方法來(lái)訪問(wèn)XML文檔中的節(jié)點(diǎn)屬性。查找節(jié)點(diǎn)的標(biāo)簽名稱(chēng)可能是最簡(jiǎn)單的方式,然后遍歷包含子節(jié)點(diǎn)列表的目錄樹(shù)。在進(jìn)行以上操作之前,你需要調(diào)用minidom.parse()方法來(lái)解析XML文檔。解析文檔后,你就可以使用childNodes屬性獲取一個(gè)包含了從根元素開(kāi)始的所有子節(jié)點(diǎn)的列表。最后調(diào)用getElementsByTagName(tag)函數(shù)來(lái)根據(jù)標(biāo)簽名稱(chēng)查找節(jié)點(diǎn)。該函數(shù)會(huì)返回一個(gè)與tag有關(guān)的所有子節(jié)點(diǎn)列表。
你還可以通過(guò)調(diào)用hasAttribute(name)方法來(lái)查看節(jié)點(diǎn)是否包含某個(gè)屬性名稱(chēng),該函數(shù)返回一個(gè)布爾值。確定屬性存在后調(diào)用getAttribute(name)方法獲取該屬性值。
在本案例中將解析一個(gè)XML文件并提取出與某個(gè)特定元素(節(jié)點(diǎn))和屬性有關(guān)的值。在該文件中,我們會(huì)從所有的節(jié)點(diǎn)中查找節(jié)點(diǎn)和address屬性,查找到的address屬性值會(huì)打印到屏幕上。
How to do it...
1.打開(kāi)IDLE,創(chuàng)建一個(gè)腳本并保存為
C:\ArcpyBook\Appendix2\XMLAccessElementAttribute.py。
2.我們以位于C:\ArcpyBook\Appendix2文件夾中的WitchFireResidenceDestroyed.xml文件為例。下面是該文件的部分內(nèi)容:
state="CA" zip="92127" country="USA" latitude="33.037187" longitude="-117.082299" />
3.從xml.dom模塊中導(dǎo)入minidom:
from xml.dom import minidom
4.解析XML文件:
xmldoc = minidom.parse("WitchFireResidenceDestroyed.xml")
5.創(chuàng)建XML文件中的節(jié)點(diǎn)列表:
childNodes = xmldoc.childNodes
6.生成一個(gè)包含所有節(jié)點(diǎn)的列表:
eList = childNodes[0].getElementsByTagName("fire")
7.循環(huán)遍歷列表中的元素,檢測(cè)是否存在address屬性。如果存在該屬性則打印該屬性值:
for e in eList:
if e.hasAttribute("address"):
print e.getAttribute("address")
8.保存并運(yùn)行腳本。你會(huì)看到如下結(jié)果顯示:
11389 Pajaro Way
18157 Valladares Dr
11691 Agreste Pl
18055 Polvera Way
18829 Bernardo Trails Dr
18189 Chretien Ct
17837 Corazon Pl
18187 Valladares Dr
18658 Locksley St
18560 Lancashire Way
........
18682 Lancashire Way
18344 Lincolnshire St
How it works...
在腳本中加載XML文檔是處理XML文件最為基礎(chǔ)的事情,你可以使用xml.dom模塊中minidom對(duì)象來(lái)完成。minidom對(duì)象包含的parse()方法可接受一個(gè)xml文檔路徑并創(chuàng)建xml文件的文檔對(duì)象模型(DOM)樹(shù)對(duì)象。
DOM樹(shù)中的childNodes屬性生成一個(gè)包含XML文件中所有節(jié)點(diǎn)的列表。隨后可以調(diào)用getElementsByTagName()方法來(lái)訪問(wèn)這些節(jié)點(diǎn)。最后一步就是循環(huán)遍歷包含在eList變量中的所有節(jié)點(diǎn)。對(duì)于每一個(gè)節(jié)點(diǎn),調(diào)用hasAttribute()方法來(lái)檢測(cè)是否包含address屬性,如果存在則調(diào)用getAttribute()方法并將屬性值打印輸出到屏幕中。
There's more...
有時(shí)候你可能需要在XML文檔中查找一個(gè)特定的文本字符串。這就需要使用xml.parsers.expat模塊。你需要從expat類(lèi)中獲取一個(gè)搜索類(lèi),之后創(chuàng)建該類(lèi)的一個(gè)對(duì)象。創(chuàng)建完成后,你可以對(duì)搜索對(duì)象調(diào)用parse()方法來(lái)查找數(shù)據(jù)。最后調(diào)用getElementsByTagName()方法根據(jù)標(biāo)簽名稱(chēng)來(lái)查找節(jié)點(diǎn),這就返回一個(gè)與標(biāo)簽名稱(chēng)有關(guān)的所有子節(jié)點(diǎn)列表。
總結(jié)
以上是生活随笔為你收集整理的arcgis python实例_ArcGIS Python编程案例(14)-五个常用Python处理任务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 运行Java程序时 Tomcat出错 显
- 下一篇: 3. 什么是icmp?icmp与ip的关