11## Contents
22
3- [ TOC]
3+ [ Overview] ( #overview )
4+
5+ [ Examples] ( #examples )
6+ - [ Reading Shapefiles] ( #reading-shapefiles )
7+ - [ Reading Shapefiles from File-Like Objects] ( #reading-shapefiles-from-file-like-objects )
8+ - [ Reading Geometry] ( #reading-geometry )
9+ - [ Reading Records] ( #reading-records )
10+ - [ Reading Geometry and Records Simultaneously] ( #reading-geometry-and-records-simultaneously )
11+ - [ Writing Shapefiles] ( #writing-shapefiles )
12+ - [ Setting the Shape Type] ( #setting-the-shape-type )
13+ - [ Geometry and Record Balancing] ( #geometry-and-record-balancing )
14+ - [ Adding Geometry] ( #adding-geometry )
15+ - [ Creating Attributes] ( #creating-attributes )
16+ - [ File Names] ( #file-names )
17+ - [ Saving to File-Like Objects] ( #saving-to-file-like-objects )
18+ - [ Editing Shapefiles] ( #editing-shapefiles )
19+ - [ Geometry and Record Balancing] ( #geometry-and-record-balancing )
20+ - [ Python \_\_ geo_interface\_\_ ] ( #python-\_\_ geo\_ interface\_\_ )
21+ - [ Testing] ( #testing )
422
523# Overview
624
@@ -385,17 +403,17 @@ data lines up with the geometry data. For example:
385403### Adding Geometry
386404
387405Geometry is added using one of three methods: "null", "point", or "poly". The
388- "null" method is used for null shapes, "point" is used for point shapes, and
389- "poly" is used for everything else.
406+ "null" method is used for null shapes, "point" is used for point shapes, "line" for lines, and
407+ "poly" is used for polygons and everything else.
390408
391409** Adding a Point shape**
392410
393411Point shapes are added using the "point" method. A point is specified by an x,
394412y, and optional z (elevation) and m (measure) value.
395413
396414
397- >>> w = shapefile.Writer()
398-
415+ >>> w = shapefile.Writer(shapefile.POINTM )
416+
399417 >>> w.point(122, 37) # No elevation or measure values
400418
401419 >>> w.shapes()[0].points
@@ -405,21 +423,45 @@ y, and optional z (elevation) and m (measure) value.
405423
406424 >>> w.shapes()[1].points
407425 [[118, 36, 4, 8]]
426+
427+ >>> w.field('FIRST_FLD', 'C')
428+ >>> w.field('SECOND_FLD', 'C')
429+
430+ >>> w.save('shapefiles/test/point')
408431
409- ** Adding a Poly shape**
432+ ** Adding a Polygon shape**
410433
411- "Poly" shapes can be either polygons or lines. Shapefile polygons must have at
434+ Shapefile polygons must have at
412435least 4 points and the last point must be the same as the first. PyShp
413- automatically enforces closed polygons. A line must have at least two points.
414- Because of the similarities between these two shape types they are created
415- using a single method called "poly".
436+ automatically enforces closed polygons.
416437
417438
418439 >>> w = shapefile.Writer()
419440
420- >>> w.poly(shapeType=3, parts=[[[122,37,4,9], [117,36,3,4]], [[115,32,8,8],
441+ >>> w.poly(parts=[[[122,37,4,9], [117,36,3,4]], [[115,32,8,8],
421442 ... [118,20,6,4], [113,24]]])
422443
444+ >>> w.field('FIRST_FLD', 'C')
445+ >>> w.field('SECOND_FLD', 'C')
446+
447+ >>> w.save('shapefiles/test/polygon')
448+
449+ ** Adding a Line shape**
450+
451+ A line must have at least two points.
452+ Because of the similarities between polygon and line types it is possible to create
453+ a line shape using either the "line" or "poly" method.
454+
455+ >>> w = shapefile.Writer()
456+
457+ >>> w.line(parts=[[[ 1,5] ,[ 5,5] ,[ 5,1] ,[ 3,3] ,[ 1,1]]] )
458+ >>> w.poly(parts=[[[ 1,3] ,[ 5,3]]] , shapeType=shapefile.POLYLINE)
459+
460+ >>> w.field('FIRST_FLD', 'C')
461+ >>> w.field('SECOND_FLD', 'C')
462+
463+ >>> w.save('shapefiles/test/polygon')
464+
423465** Adding a Null shape**
424466
425467Because Null shape types (shape type 0) have no geometry the "null" method is
@@ -439,51 +481,114 @@ The writer object's shapes list will now have one null shape:
439481
440482Creating attributes involves two steps. Step 1 is to create fields to contain
441483attribute values and step 2 is to populate the fields with values for each
442- shape record.
443-
444- The following attempts to create a complete shapefile. The attribute and
445- field names are not very creative:
446-
447-
448- >>> w = shapefile.Writer(shapefile.POINT)
449- >>> w.point(1,1)
450- >>> w.point(3,1)
451- >>> w.point(4,3)
452- >>> w.point(2,2)
453- >>> w.field('FIRST_FLD')
454- >>> w.field('SECOND_FLD','C','40')
455- >>> w.record('First','Point')
456- >>> w.record('Second','Point')
457- >>> w.record('Third','Point')
458- >>> w.record('Fourth','Point')
459- >>> w.save('shapefiles/test/point')
460-
461- >>> w = shapefile.Writer(shapefile.POLYGON)
462- >>> w.poly(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])
463- >>> w.field('FIRST_FLD','C','40')
464- >>> w.field('SECOND_FLD','C','40')
465- >>> w.record('First','Polygon')
466- >>> w.save('shapefiles/test/polygon')
467-
468- >>> w = shapefile.Writer(shapefile.POLYLINE)
469- >>> w.line(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])
470- >>> w.poly(parts=[[[1,3],[5,3]]], shapeType=shapefile.POLYLINE)
471- >>> w.field('FIRST_FLD','C','40')
472- >>> w.field('SECOND_FLD','C','40')
473- >>> w.record('First','Line')
474- >>> w.record('Second','Line')
475- >>> w.save('shapefiles/test/line')
484+ shape record.
476485
477- You can also add attributes using keyword arguments where the keys are field
478- names.
486+ There are several different field types, all of which support storing None values as NULL.
479487
488+ Text fields are created using the 'C' type, and the third 'size' argument can be customized to the expected
489+ length of text values to save space:
480490
481- >>> w = shapefile.Writer(shapefile.POLYLINE)
482- >>> w.line(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])
483- >>> w.field('FIRST_FLD','C','40')
484- >>> w.field('SECOND_FLD','C','40')
485- >>> w.record(FIRST_FLD='First', SECOND_FLD='Line')
486- >>> w.save('shapefiles/test/line')
491+
492+ >>> w = shapefile.Writer()
493+ >>> w.field('TEXT', 'C')
494+ >>> w.field('SHORT_TEXT', 'C', size=5)
495+ >>> w.field('LONG_TEXT', 'C', size=250)
496+ >>> w.null()
497+ >>> w.record('Hello', 'World', 'World'*50)
498+ >>> w.save('shapefiles/test/dtype')
499+
500+ >>> r = shapefile.Reader('shapefiles/test/dtype')
501+ >>> assert r.record(0) == ['Hello', 'World', 'World'*50]
502+
503+ Date fields are created using the 'D' type, and can be created using either
504+ date objects, lists, or a YYYYMMDD formatted string.
505+ Field length or decimal have no impact on this type:
506+
507+
508+ >>> from datetime import date
509+ >>> w = shapefile.Writer()
510+ >>> w.field('DATE', 'D')
511+ >>> w.null()
512+ >>> w.null()
513+ >>> w.null()
514+ >>> w.null()
515+ >>> w.record(date(1998,1,30))
516+ >>> w.record([1998,1,30])
517+ >>> w.record('19980130')
518+ >>> w.record(None)
519+ >>> w.save('shapefiles/test/dtype')
520+
521+ >>> r = shapefile.Reader('shapefiles/test/dtype')
522+ >>> assert r.record(0) == [date(1998,1,30)]
523+ >>> assert r.record(1) == [date(1998,1,30)]
524+ >>> assert r.record(2) == [date(1998,1,30)]
525+ >>> assert r.record(3) == [None]
526+
527+ Numeric fields are created using the 'N' type (or the 'F' type, which is exactly the same).
528+ By default the fourth decimal argument is set to zero, essentially creating an integer field.
529+ To store floats you must set the decimal argument to the precision of your choice.
530+ To store very large numbers you must increase the field length size to the total number of digits
531+ (including comma and minus).
532+
533+
534+ >>> w = shapefile.Writer()
535+ >>> w.field('INT', 'N')
536+ >>> w.field('LOWPREC', 'N', decimal=2)
537+ >>> w.field('MEDPREC', 'N', decimal=10)
538+ >>> w.field('HIGHPREC', 'N', decimal=30)
539+ >>> w.field('FTYPE', 'F', decimal=10)
540+ >>> w.field('LARGENR', 'N', 101)
541+ >>> nr = 1.3217328
542+ >>> w.null()
543+ >>> w.null()
544+ >>> w.record(INT=int(nr), LOWPREC=nr, MEDPREC=nr, HIGHPREC=-3.2302e-25, FTYPE=nr, LARGENR=int(nr)*10**100)
545+ >>> w.record(None, None, None, None, None, None)
546+ >>> w.save('shapefiles/test/dtype')
547+
548+ >>> r = shapefile.Reader('shapefiles/test/dtype')
549+ >>> r.record(0)
550+ [1, 1.32, 1.3217328, -3.2302e-25, 1.3217328, 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L]
551+ >>> r.record(1)
552+ [None, None, None, None, None, None]
553+
554+
555+ Finally, we can create boolean fields by setting the type to 'L'.
556+ This field can take True or False values, or any string whose first character is one of YyTt (True) or NnFf (False).
557+ None is interpreted as missing.
558+
559+
560+ >>> w = shapefile.Writer()
561+ >>> w.field('BOOLEAN', 'L')
562+ >>> w.null()
563+ >>> w.null()
564+ >>> w.null()
565+ >>> w.null()
566+ >>> w.null()
567+ >>> w.record(True)
568+ >>> w.record("Yes")
569+ >>> w.record(False)
570+ >>> w.record("No")
571+ >>> w.record(None)
572+ >>> w.save('shapefiles/test/dtype')
573+
574+ >>> r = shapefile.Reader('shapefiles/test/dtype')
575+ >>> assert r.record(0) == [True]
576+ >>> assert r.record(1) == [True]
577+ >>> assert r.record(2) == [False]
578+ >>> assert r.record(3) == [False]
579+ >>> assert r.record(4) == [None]
580+
581+
582+ You can also add attributes using keyword arguments where the keys are field names.
583+
584+ >>> w = shapefile.Writer()
585+ >>> w.field('FIRST_FLD','C','40')
586+ >>> w.field('SECOND_FLD','C','40')
587+ >>> w.record('First', 'Line')
588+ >>> w.record(FIRST_FLD='First', SECOND_FLD='Line')
589+ >>> assert w.records[0] == w.records[1]
590+
591+
487592
488593### File Names
489594
0 commit comments