7.3 Working with ZIP files using zipfile
GIS数据集很大, 以shape文件为例,包含了shp、shx、dbf、prj等,因此通常是将一个shape压缩到一个zip等进行传输。ZIP作为一种无损数据压缩格式,可以通过电子邮件等共享。在windows中,还有其他几种格式:.7z、.dmg、.gz和.tar等,在原书中只对ZIP格式进行介绍,其他格式也可以完成类似ZIP文件的步骤。
使用Python处理ZIP文件是使用zipfile
模块完成的,它是标准库的一部分。Python还有一个内置的zip()
函数,它与迭代器一起工作,与zip文件无关。zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
zipfile
模块的主类是zipfile。在典型的脚本中,通过指向现有ZIP文件或创建新的ZIP文件来创建ZipFile对象,然后使用该对象的方法执行特定的任务。通过指向现有ZIP文件创建ZipFile对象的工作方式如下:
import zipfile
zip = open("C:/Demo/test.zip", "rb")
myzip = zipfile.ZipFile(zip)
参数rb
表示您以二进制模式读取文件内容。可以使用namelist()
方法检查ZIP 文件的内容,如下所示:
for file in myzip.namelist():
print(file)
可以使用相同的方法迭代ZIP存档中的所有文件,并逐个提取它们:
for file in myzip.namelist():
out = open(file, "wb")
out.write(myzip.read(file))
out.close()
这个代码将每个文件提取到当前工作目录,默认情况下,该目录是脚本的位置。您可以使用 os.chdir()
更改此目录。作为替代,可以在保存每个本地文件时指定路径:
out = open("C:/Temp/" + file, "wb")
然而,在大多数情况下,您不需要逐个迭代ZIP文件中的文件,因为只需要提取所有文件,这可以使用extractll()
方法更容易地完成。为清晰起见,整个脚本如下所示:
import zipfile
zip = open("C:/Demo/test.zip", "rb")
myzip = zipfile.ZipFile(zip)
myzip.extractall()
可以使用以下命令指定要提取文件的文件夹:
myzip.extractall("C:/Temp")
可以使用zipfile模块为一个或多个文件创建新的ZIP存档。通过指定一个尚不存在的新.zip文件并使用“w
”参数具有写入权限,可以创建ZipFile对象。也可以指定压缩类型。如果省略了压缩类型,则使用默认ZIP_STORED 将单个文件添加到ZIP存档的代码如下:
import zipfile
zfile = zipfile.ZipFile("mytiff.zip", "w",
zipfile.ZIP_DEFLATED)
zfile.write("landcover.tif")
zfile.close()
同样的方法可以用于遍历目录中的文件列表。脚本遍历列表,并使用write()
方法将每个文件添加到同一ZIP存档中。例如,以下脚本使用os.listdir
创建文件夹中所有文件的列表,然后添加每个文件(如果它们使用特定文件扩展名):
import os
import zipfile
zfile = zipfile.ZipFile("shapefiles.zip", "w")
files = os.listdir("C:/Project")
for f in files:
if f.endswith(("shp", "dbf", "shx")):
zfile.write("C:/Project/" + f)
zfile.close()
大多数shape文件都包含额外的扩展文件。一种更稳健的方法是使用ArcPy函数(如ListFeatureClasses()
)创建文件夹中所有shapefile的列表,然后添加具有相同 名称的所有文件,而不考虑其文件扩展名。
也可以使用整个文件夹及其内容。为此,请使用os.walk()
创建文件夹中所有文件的路径列表。这个方法也保留了文件夹结构,以下脚本为一个特定文件夹(包括所有子文件夹)的全部内容创建一个ZIP存档:
import os
import zipfile
mydir = "C:/Demo/Project"
zfile = zipfile.ZipFile("newzip.zip", "w")
for root, dirs, files in os.walk(mydir):
for file in files:
filepath = os.path.join(root, file)
zfile.write(filepath)
zfile.close()
这个方法可用于为包含一个或多个文件地理数据库的文件夹创建ZIP存档,因为从文件管理的角度来看,文件地理数据库是一个包含许多文件的文件夹。使用这些单独的文件是不切实际的,因此您可以将整个文件夹添加到ZIP存档中。