[GIS] Export selected feature/s to shapefile with open source python library

exportfionaogrpyshppython

I need to be able to select one feature/record at a time within a polygon shapefile, regardless of how many shapes it contains, using open source python libraries (e.g., OGR, pyshp, fiona). Then I want to use each feature/record in a different function that requires a shapefile format. Below is what I'm attempting with pyshp:

shp = shapefile.Reader(file)  ## open and read the shapefile
shp = shp.shapes()  ## read the geometry information of each shape record
shpInPoly = []  ## empty array that will contain the features in the file
for i in shp:
   shpInPoly.append(i)

Then I'd assume I could grab the first feature in the array of appended features like this:

currentPolygon = shpInPoly[0]

And use the "currentPolygon" variable in my other function with the first record/feature in the original shapefile.

But it doesn't work. The error I get in my other function which requires shapefile inputs is "shapefile.ShapefileException: Shapefile Reader requires a shapefile or file-like object." The other alternative, per the question title (and what I'm thinking is likely best), would be to export that selected feature/record and all its content (geometry and fields) to a new shapefile, to achieve the same purpose of using that in another shapefile-requring function. The only posts I found that attempt something similar are Exporting Selected Feature to New Shapefile using ArcPy? and Splitting shapefile into many shapefiles with open source?, but I can't use ArcPy.

Any ideas?

Best Answer

If your other function expects a single shapefile input, then you need to split each polygon in the polygon shapefile into its own shapefile. Right now you are passing subsections of a shapefile and the other function is complaining. The code will look something like the following.

import shapefile

# path and name of the input shapefile
input_shp = "my_polys.shp"

# read the input shapefile
r = shapefile.Reader(input_shp)

# list of filenames for the split 
# polygon shapefiles
shp_files = []

# Loop through each polygon and dbf record,
# and create a new shapefile. We add an
# enumeration to give us a number for each
# new shapefile name.
for i, shapeRec in enumerate(r.iterShapeRecords()):
    # polygon
    shape = shapeRec.shape
    # dbf record
    rec = shapeRec.record
    # Create a new shapefile writer
    w = shapefile.Writer(shapefile.POLYGON)
    # Copy the dbf fields from the original shapefile
    w.fields = list(r.fields)
    # Add the polygon to the new shapefiles list of shapes
    w._shapes.append(shape)
    # Do the same for the dbf record
    w.records.append(rec)
    # Create a unique name for each shapefle
    # based on the enumeration index
    shp_name = "poly_{}.shp".format(i)
    # Save the shapefile and append the 
    # name to a list of names
    w.save(shp_name)
    shp_files.append(shp_name)

# Now you can loop through the list
# of shapefile names and pass them
# to the other function
for shp in shp_files:
    my_other_function(shp)

# Or if the other function expects
# a pyshp shapefile object:
for shp in shp_files:
    r = shapefile.Reader(shp)
    my_other_function(r)
Related Question