2

EDIT: I've tried running the code linked in the duplicate flag, it's posted here for reference, and it doesn't run. I had already referred to that answer in my initial post.

My problem

Downloaded shapefile is missing .shx file and trying to use pyshp to build it on a mac.*

I've tried this code that I've picked up from the pyshp documentation. When checking the r.shapes and r.records, it looks like all of the info is there.

myshp = open("Stockton/Stockton.shp", "rb")
mydbf = open("Stockton/Stockton.dbf", "rb")
r = shapefile.Reader(shp=myshp, dbf=mydbf, shx=None)

In the documentation, it looks like each record and shape is being added one at a time. Is there a method I'm missing? Or could a list comprehension be used here to loop through everything?**

Data and References

I've downloaded the Microsoft Building Data for Stockton CA from here. I've tried to follow the code from the answer here

    # Build a new shx index file
    #Code by Joel Lawhead http://geospatialpython.com/2011/11/generating-shapefile-shx-files.html
    import shapefile
    # Explicitly name the shp and dbf file objects
    # so pyshp ignores the missing/corrupt shx
    myshp = open("Stockton/Stockton.shp", "rb")
    mydbf = open("Stockton/Stockton.dbf", "rb")
    r = shapefile.Reader(shp=myshp, shx=None, dbf=mydbf)
    w = shapefile.Writer(r.shapeType)
    # Copy everything from reader object to writer object
    w._shapes = r.shapes()
    w.records = r.records()
    w.fields = list(r.fields)
    # saving will generate the shx
    w.save("myshape")

but get this error:

TypeError                                 Traceback (most recent call last)
<ipython-input-94-345df1656b96> in <module>
      7 mydbf = open("Stockton/Stockton.dbf", "rb")
      8 r = shapefile.Reader(shp=myshp, shx=None, dbf=mydbf)
----> 9 w = shapefile.Writer(r.shapeType)
     10 # Copy everything from reader object to writer object
     11 w._shapes = r.shapes()

...

TypeError: expected str, bytes or os.PathLike object, not int

*Because I'm using a Mac, none of the solutions here seem like they would work.

**Still fairly new to Python so please forgive wrong/confusing terminology.

5
  • I'm not quite sure how this is a duplicate as the question linked doesn't answer my question. I've run that code and posted the error it gives me.
    – maxo
    Commented Jul 31, 2019 at 22:52
  • 1
    The OGR options should still work on your Mac. OGR is part of GDAL, which can be installed and run on a Mac. There's a bit of a learning curve though. Commented Jul 31, 2019 at 23:01
  • There exist datasets for which the .shx cannot be recovered, like shapefiles with CAD objects in them. The CAD data live in a hole between the documented geometry data, and the size of the hole can only be determined by peeking at the next record start.
    – Vince
    Commented Aug 1, 2019 at 0:14
  • 1
    I agree, this isn't a dupe. You need to pass a filepath as the first arg, or use keyword args shapefile.Writer(target='path/to/shx', shapeType=r.shapeType)
    – user2856
    Commented Aug 1, 2019 at 4:37
  • gis.stackexchange.com/help/someone-answers
    – user2856
    Commented Dec 9, 2021 at 7:27

1 Answer 1

6

That example code you link to looks like it's out of date (for an old version of pyshp).

This works (based on bits and pieces from the docs):

shp = r"path/to/shp"  # NOTE no .shp extension

from shapefile import (Reader, Writer)

try:  # Py2 (I haven't actually tested on python 2...)
    from StringIO import StringIO as IO
except ImportError:  # Py3
    from io import BytesIO as IO

with IO() as shpio, IO() as dbfio:  # Don't overwrite existing .shp, .dbf
    with Reader(shp) as r, Writer(shp=shpio, dbf=dbfio, shx=shp+'.shx') as w:
        w.fields = r.fields[1:]  # skip first deletion field
        for rec in r.iterShapeRecords():
            w.record(*rec.record)
            w.shape(rec.shape)
2
  • You just SAVED MY ASS. THANK YOU! Commented Sep 22, 2022 at 15:01
  • If you're using fiona or geopandas to read in shapefiles, you can also add the following at the start of your script: import gdal; gdal.SetConfigOption('SHAPE_RESTORE_SHX', 'YES') Commented Feb 27, 2023 at 8:31

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.