Presume I have an archive, foo.zip. It contains the parts of a shapefile: foo.shp, foo.dbf, foo.shx, foo.prj, and foo.cpg. I want to work with this shapefile in python, using pyshp, AKA the shapefile library.

Right now, I can extract the archive to disk, then read in the shapefile:

r = shapefile.Reader('foo')

I have quite a few such archives, though, and it would be nice to be able to read in these files without having to first extract each archive. According to pyshp's documentation, you can read in a file-like object with syntax like this:

myshp = open('foo.shp', 'rb')
mydbf = open('foo.dbf', 'rb')
r = shapefile.Reader(shp=myshp, dbf=mydbf)

And I quote: "This feature is very powerful and allows you to load shapefiles from a url, from a zip file, serialized object, or in some cases a database."

Thus I have tried creating a file-like object from my archive. First, creating the archive:

archive = zipfile.ZipFile('foo.zip')

Works fine. But if I then try

r = shapefile.Reader(archive.open('foo.shp')

I get the error, "shapefile.ShapefileException: Shapefile Reader requires a shapefile or file-like object."

That's legit; I should be passing it a file-like object. So I tried modifying the documentation's canonical example:

myshp = archive.open('foo.shp', 'r')
mydbf = archive.open('foo.dbf', 'r')
r = shapefile.Reader(shp=myshp, dbf=mydbf)

But this produces the error, "io.UnsupportedOperation: seek".

For what it is worth, I cannot use 'rb' as an option with archive.open(). If I do, I am told, "RuntimeError: open() requires mode 'r', 'U', or 'rU'". Also, using "archive.read()" instead of "archive.open()" just produces the "...requires a shapefile or file-like object" error.

I am stumped. As far as I can tell, I have created archive correctly, I have correctly used archive.open() to grab files as file-like objects, and I have used the correct syntax to have pyshp read from a file-like object. And yet, these errors. Does anyone have any idea what I'm doing wrong here? Has anyone had success passing file-like objects from zip archives to pyshp?

2 Answers 2


I have been using StringIO for reading zipped shapefiles with pyshp and it worked fine.

#shapefile.__version__ '1.2.3'

from __future__ import print_function
import zipfile
import StringIO
import shapefile

zipshape = zipfile.ZipFile(open(r'C:\GIS\Temp\RoadsShapefileFolder.zip', 'rb'))
dbfname, _, shpname, _, shxname = zipshape.namelist()
r = shapefile.Reader(shp=StringIO.StringIO(zipshape.read(shpname)),



['Roads.dbf', 'Roads.prj', 'Roads.shp', 'Roads.shp.xml', 'Roads.shx']
[279629.7664999999, 6137207.9419, 916929.7043000003, 7595571.024099998]

Make sure you access the right files within the zip as they are sorted alphabetically.

  • Thank you--that seemed to do the trick. On this other thread, someone noted that "read returns a string with the file's contents; open returns a file-like object." It seems telling that reading and then passing through StringIO works, while the straight open does not seem to. Odd--but I'll take this solution! Jul 27, 2017 at 17:01
  • 4
    In python 3 you should use BytesIO from the io package.
    – webelo
    Mar 7, 2018 at 19:16
  • Can someone show me an example using Bytes io? I am still getting shapefile.ShapefileException: Shapefile Reader requires a shapefile or file-like object. from ``` as_like = io.BytesIO(as_zips.read(shapes[0]) )``` Apr 23, 2020 at 21:10

These days, opening a shapefile contained in a zip works just fine:

def ecoregion():
    >>> eco = ecoregions()
    >>> eco.fields
    [('DeletionFlag', 'C', 1, 0),
     ['OBJECTID', 'N', 32, 10],
     ['ECO_NAME', 'C', 150, 0],
     ['BIOME_NUM', 'N', 32, 10],
     ['BIOME_NAME', 'C', 254, 0],
     ['REALM', 'C', 254, 0],
     ['ECO_BIOME_', 'C', 254, 0],
     ['NNH', 'N', 11, 0],
     ['ECO_ID', 'N', 11, 0],
     ['SHAPE_LENG', 'N', 32, 10],
     ['SHAPE_AREA', 'N', 32, 10],
     ['NNH_NAME', 'C', 64, 0],
     ['COLOR', 'C', 7, 0],
     ['COLOR_BIO', 'C', 7, 0],
     ['COLOR_NNH', 'C', 7, 0],
     ['LICENSE', 'C', 64, 0]]
    zipshape = zipfile.ZipFile(
        (Path(__file__).parent.parent / "ecoregions/Ecoregions2017.zip").open("rb"))
    shape = shapefile.Reader(
    return shape

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.