Overview of PyShp
master.shp (geometry), .shx (index), and .dbf (attribute data) file formats. Because it is written in pure Python, it is highly portable and does not require external C dependencies to handle standard GIS vector data.repository·master·Indexed 22 days ago
https://github.com/geospatialpython/pyshpA pure Python library for reading and writing ESRI Shapefiles, supporting .shp (geometry), .shx (index), and .dbf (attribute data) formats without requiring external C libraries. It provides Reader and Writer classes, supports GeoJSON conversion via __geo_interface__, and allows reading from local files, Zipfiles, and URLs.
.shp (geometry), .shx (index), and .dbf (attribute data) file formats. Because it is written in pure Python, it is highly portable and does not require external C dependencies to handle standard GIS vector data.PyShp implements specific logic to handle the complexities of storing Unicode in DBF files, which traditionally expect ASCII.
size or the 10-byte field name limit. It does this by truncating one code point at a time to avoid corrupting multi-byte characters. A warning is issued if truncation occurs.A valid shapefile requires an equal number of shapes and records. If you add shapes and records in different orders or skip some, the file may become corrupt.
To prevent this, use one of these two mechanisms:
w.autoBalance = True (or 1). PyShp will automatically add null shapes or null records to keep the counts synchronized.w.balance() at any time to synchronize the geometry and attribute sides.# Enable auto-balancing
>>> w.autoBalance = 1
>>> w.record("row", "three")
>>> w.point(4, 4)
# Manual balancing
>>> w.autoBalance = 0
>>> w.record("row", "five")
>>> w.point(5, 5)
>>> w.balance()Version 3.0.0 introduced several breaking changes for users migrating from older versions:
Field namedtuple instead of a list.FieldType enum members.bbox, mbox, and zbox attributes are now Namedtuple objects.Writer class no longer mutates Shape objects.Null, Multipatch, Point, Polyline, Multipoint, and Polygon (including M and Z variants). While Reader and Writer remain compatible with the base Shape class, these specific subclasses are now available.The shapefile.Writer class uses a streaming approach. Geometries and records are written to disk immediately when shape() or record() is called. This allows for writing arbitrarily large files without consuming excessive memory.
Important: You must call w.close() (or ensure the writer is garbage collected) to trigger the calculation and writing of the final header information to the beginning of the file.
import shapefile
w = shapefile.Writer('output_file')
w.field('NAME', 'C')
w.record('Example Name')
w.shape([ [0,0], [1,1], [1,0] ])
w.close() # Essential to write the headerVersion 2.0.0 introduced major architectural changes that are incompatible with version 1.x:
Reader returns unicode and Writer accepts unicode.Reader and Writer classes; the Editor class has been removed.Writer uses a streaming approach to minimize memory usage. You specify the filepath/destination and text encoding when creating the Writer, and files are written incrementally with each call to shape() and record().Reader supports the context manager pattern (using with).Reader is iterable and supports len().Reader supports the geo interface.Reader attributes elevation and measure were renamed to zbox and mbox to clarify they represent min/max values.When working with very large shapefiles, avoid using records() or shapes() as they attempt to load the entire file into memory, which can cause a MemoryError. Instead, use iterator methods that process the file contents one at a time to keep memory usage minimal.
Use the following methods for streaming data:
iterShapes(): Iterates through geometries.iterRecords(): Iterates through attribute records.iterShapeRecords(): Iterates through both geometry and records.Reader object (e.g., for shapeRec in sf:) is equivalent to iterShapeRecords().sf = shapefile.Reader("path_to_large_file.zip")
# Use iterators to avoid MemoryError
for shapeRec in sf.iterShapeRecords():
# process shape and record
passTo create a shapefile, instantiate a shapefile.Writer with a base file path. File extensions are optional; if provided, PyShp ignores them. You can specify a base name for all three component files (shp, dbf, shx) or specify individual names for specific file types. If a file type is not assigned a name, it will not be saved.
>>> w = shapefile.Writer('tests/shapefiles/test/testfile')
>>> w.field('field1', 'C')
# To write only a DBF file:
>>> w = shapefile.Writer(dbf='tests/shapefiles/test/onlydbf.dbf')A .prj file stores the map projection (WKT string) and is required for GIS software to locate geometry correctly. The .prj file must have the same base name as your shapefile (e.g., myFile.prj for myFile.shp).
You can create one manually by writing a Well-Known-Text (WKT) string to a file with the .prj extension.
# Example: Creating a WGS 84 .prj file
filename = 'myPoints'
with open("{}.prj".format(filename), "w") as prj:
wkt = 'GEOGCS["WGS 84",'
wkt += 'DATUM["WGS_1984",'
wkt += 'SPHEROID["WGS 84",6378137,298.257223563]]'
wkt += ',PRIMEM["Greenwich",0],'n wkt += 'UNIT["degree",0.0174532925199433]]'
prj.write(wkt)To edit a shapefile (e.g., to remove fields or filter records), you must read the original file record-by-record and write the desired subset to a new file using shapefile.Writer.
Workflow:
Writer.w.field().Reader using iterShapeRecords() (optionally with the fields argument to limit data read).w = shapefile.Writer('edited_output')
r = shapefile.Reader('original_file')
keep_fields = ['ID', 'VALUE']
# Define new schema
for field in r.fields[1:]:
if field[0] in keep_fields:
w.field(*field)
# Write filtered data
for shapeRec in r.iterShapeRecords(fields=keep_fields):
w.record(*shapeRec.record)
w.shape(shapeRec.shape)
w.close()While the Writer class automatically closes files and writes headers when garbage collected, it is recommended to call .close() manually to prevent data loss in case of crashes. Alternatively, use the with statement to ensure files are properly closed and headers are written automatically when exiting the block.
>>> with shapefile.Writer("tests/shapefiles/test/contextwriter") as w:
... w.field('field1', 'C')
... passBy default, PyShp provides logging information and warnings about non-critical issues. You can control this behavior using the shapefile.VERBOSE constant or by configuring the shapefile logger via the standard logging module.
To suppress all output, set shapefile.VERBOSE = False or set the logging level for the shapefile namespace to ERROR.
# Option 1: Use the module constant
import shapefile
shapefile.VERBOSE = False
# Option 2: Use the logging module
import logging
logging.getLogger('shapefile').setLevel(logging.ERROR)