Digital Geography

29. November 2014

A small tool with Python: the shapefile archiver

Let me introduce to you, guys, my first Python tool: “Shapefile Archiver”. Usually, I face lots of problems in managing my shapefiles. My first problem is backing them up in a decent way, especially, before starting some experimental things on them (That sounds scary!), while the second problem is that Finder/Windows explorer doesn’t tell me about the shapefile more than its name!. Moreover, Finder/Windows explorer shows the shapefile as a bunch of files (*.shp, *.prj, *.shx, *.dbf,…) which makes me feel annoyed especially because I’m too lazy to open QGIS browser or ArcCataloge every time I want to explore my shapefiles. Therefore, I’ve decided to program a tool to sort all these problems out by a click 🙂 Since I love challenge, I’ve decided to do that with a new programming language to me (Yes!!, you guessed it, it is Python). Let’s start.

My pseudocode was as follows:

  • Create a folder entitled “Archive” .
  • Detect the shapefiles in the main folder.
  • Create a subfolder for every shapefile with the same name of that shapefile inside the “Archive” folder.
  • Copy every shapefile to its subfolder.
  • Create a text file, in that subfolder, contains the basic information about this shapefile, i.e. (Name, Type, Is it spatially referenced or not?, type of referencing (projected or geographic), and the unit).
#In the next couple of lines, we will Import the required libraries
import glob, sys, os, shutil
from osgeo import ogr
# To be able to detect the shapefiles, we, first, need to create a shapefile driver:
driver = ogr.GetDriverByName('ESRI Shapefile')
#Now, we will use “glob.glob” to look for any file that has a “.shp” extension. We need this step to detect the shapefiles form other types of files
lstShapefiles= glob.glob("*.shp")
As I mentioned above, this script is meant to create an “Archive” folder just inside the main folder (with the shapefiles). In order to do so, we should know where the script file is located.
x = os.getcwd() # Getting the path of where the script file is located.
#Then, creating the folder “Archive” to that path
thesubpath = str(x+"\\Archive")
Checking if the folder does exist or not, if so, it will be over written! “This is incredibly important if you want to update your archiving information. Without these three lines, an error shows up if you want to back up your files again.
if os.path.exists(thesubpath): # does it exist?
	shutil.rmtree(thesubpath) # Yes. Then, overwrite it
os.mkdir (thesubpath) # No. Then, create a new one
Well, till now, there is nothing “geospatial” in the code. (The geospatial is coming, guys, right now!!)
# looping through the shapefiles to get (the Name, Type, Is the shapefile spatially referenced or not?, type of referencing (projected or geographic), and the unit)
for shpFile in lstShapefiles:
	dataSource = driver.Open(shpFile,0) # the 0 is for reading only, so nothing will affect the data.
	# Get the Layer
	myLayer=dataSource.GetLayer()
	# Get the Geometry type. The output of this is either “1” for point, “2” for polyline or “3” for polygon.
	shapeType=myLayer.GetGeomType()
	#a dictionary is used here to refer in “spoken language” what the type of the shapefile is
	dectype={1:"Point",2:"Polyline",3:"Ploygon"}
	# Get the Coordinate System.
	CoordSys = myLayer.GetSpatialRef()
In the next few lines, we will create a subfolder “_Info” for each shapfile.
#Create the subfolder with the same name of the shapefile
     thenewpath = str(thesubpath+"\\"+shpFile[:-4]+"_"+"Info")
     print "\n \nThe path of the sub folder is: "+thenewpath
     print "The following files have been moved to the previous folder"

#Checking if the folder does already exist, if so, it will be over written
     if os.path.exists(thenewpath):  # does it exist?
         shutil.rmtree(thenewpath)    # Yes. Then, overwrite it
     os.mkdir (thenewpath)             # No. Then, create a new one
Well, so far, we created a folder entitled “Archive”. Then, detected the shapefiles in the main folder. After that, we created a subfolder for every shapefile with the same name of that shapefile inside the “Archive” folder. Now, we’ll write a code to copy every shapefile to its subfolder.
# looping through the shapefiles and moving them to the subfolders
     lstfiles= glob.glob(shpFile[:-3]+"*") # since the sapefile consists of more that one file with different extensions, I’ll use the “*” instead of listing all possible extensions
# copying process
     for File in lstfiles:
          dir_src = x+"\\"+File # defining the source of the file
          dir_dst = thenewpath+"\\"+File # defining the destination of the file
          print File
In the next bunch of lines, we’ll write a code to create a text file in the subfolders to write up the basic information about each shapefile.
#Make a summary
          f=open(thenewpath+"\\"+shpFile[:-4]+".txt",'w') # w is for writing
          if CoordSys.IsProjected(): # is it projected?
               f.write("Name: "+shpFile[:-4]+"\n"+"Type: "+dectype[shapeType]+"\n"+"This shapefile is spatially referenced"+"\n"+"The coordinate System is Linear"+"\n"+"The unit is: "+CoordSys.GetLinearUnitsName())
elif CoordSys.IsGeographic(): # is it geographic?
               f.write("Name:\t"+shpFile[:-4]+"\nType:\t"+dectype[shapeType]+"\n"+"This shapefile is spatially referenced"+"\n"+"The coordinate System is Geographic"+"\n"+"The unit is: degree")
else:
               f.write("Name:\t"+shpFile[:-4]+"\nType:\t"+dectype[shapeType]+"\n"+"This shapefile is not referenced")
          f.close
#Copying the files to the subfolder
          shutil.copyfile(dir_src,dir_dst)
print "\n \nDone :)"
All what you have to do is to paste this script file  among your shapefiles, and it will do the rest The results:

the position

 

the dialog

 

the result

Your comments are more than welcomed.
  • pimplbe

    Hi Mohammed,
    thanks for code sharing. I don’t have the osgeo library installed and can’t find it using pip. Where can i find it?

  • Ranjit Shrestha

    How to use .zip file of DEM in arc gis

    • Riccardo Klinger

      unzip and import the raster file. I don’t know, whats inside the zip…