I'm getting the following error when trying to add a property to a .shp file using fiona in python: Traceback (most recent call last):

  File "<ipython-input-38-5f04c3b56601>", line 17, in <module>

  File "/Users/alex/anaconda/lib/python2.7/site-packages/fiona/collection.py", line 402, in __exit__

  File "/Users/alex/anaconda/lib/python2.7/site-packages/fiona/collection.py", line 386, in close

  File "/Users/alex/anaconda/lib/python2.7/site-packages/fiona/collection.py", line 376, in flush

  File "fiona/ogrext.pyx", line 939, in fiona.ogrext.WritingSession.sync (fiona/ogrext.c:15649)

RuntimeError: Failed to sync to disk

Here is my code - I'm adding a dummy property 'jazz' for now but I have many properties with both float and string types that I want to add once I figure out how to get it to work...

import random
import fiona

with fiona.open("data/subplace_maps/SP_SA_2011.shp") as input:
    schema2 = input.schema.copy()
    schema2['properties']['jazz'.decode('utf-8')] = 'str:50'
    temp = input.crs
    with fiona.open('data/subplace_maps/output.shp', 'w', crs=input.crs, driver=input.driver, schema=schema2) as sink:
        # iterate over shapefile shapes
        j = 0
        for elem in input:
            # update progress
            if(j % 500 == 0):
                print j,'/',len(input)
            ja = ('jazz' + str(random.random())).decode('utf-8')

print 'done'

3 Answers 3


Fiona works with Python dictionaries (schema, features) and and more specifically Ordered Dictionaries

shape = fiona.open("a_shapefile.shp")
# schema of the shapefile
{'geometry': 'Point', 'properties': OrderedDict([(u'id', 'str:10')])}
# keys of the dictionary
['geometry', 'properties']
# first feature of the shapefile
elem = shape.next()
# keys of the dictionary
['geometry', 'type', 'id', 'properties']
#  properties of the first feature
OrderedDict([(u'id', u'1')])
#keys of the dictionary
# value of the field/key 'id'

When you modify the schema of your shapefile you simply add a new key:value to the dictionary

 schema2 = input.schema.copy() 
 # or
 schema2 = input.schema
 # add a new field to the dictionary (key:value)
 schema2['properties']['jazz'] = 'str:50' 
 print schema2
 {'geometry': 'Point', 'properties': OrderedDict([(u'id', 'int:10'), ...., (u'jazz', 'str:50')])}

And when you want to add/modify a value in the jazz field you simply add/modify the value of the key [jazz] (= elem['properties']['jazz'])

 with fiona.open('output.shp', 'w', crs=input.crs, driver=input.driver, schema=schema2) as sink:
    for elem in input:
        # elem is a dictionary with keys
        # original shapefile
        print "original: ", elem['properties']
        # now add the new value to the dictionary
        ja = ('jazz' + str(random.random()))
        elem['properties']['jazz'] = ja 
        print "modified: ", elem['properties']

original:  OrderedDict([(u'id', None)])
modified:  OrderedDict([(u'id', None),('jazz', 'jazz0.551109926166')])

Control (all is dictionaries)

test = fiona.open('output.shp')
elem = test.next()
{'geometry': {'type': 'Point', 'coordinates': (0.21784342830509873, 0.37825773080975944)}, 'type': 'Feature', 'id': '0', 'properties': OrderedDict([(u'id', u'1'), (u'jazz', u'jazz0.551109926166')])}
{'type': 'Point', 'coordinates': (0.21784342830509873, 0.37825773080975944)}
(0.21784342830509873, 0.37825773080975944)
OrderedDict([(u'id', u'1'), (u'jazz', u'jazz0.551109926166')])

As far as I know, the Fiona package in the default Anaconda channel is broken. Is that the one you're using? If so, can you try the "conda-forge" channel instead?

  • hmm it's worked for extracting features out of shapefiles, just exporting not working... I ended up doing some ninja tactics by directly altering a topojson version of the shp file by parsing the json object and adding the features i need - see below :)
    – alxcnwy
    May 2, 2016 at 14:23

I couldn't get it to work in time for my deadline so ended up converting the .shp file to topojson and adding the features directly to the json (the final output I needed was topojson for d3 anyway...)

see below:

import json
import csv
from collections import OrderedDict
import io

# read proeprties to be added to topojson
csvdata = csv.DictReader(open('data/addtoshapes.csv', 'rb'))
csvdict = OrderedDict()
for line in csvdata:
    spcode = line['spcode']
    del line['spcode']

# iterate over existing topojson file and add properties from csvdata    
# map geometry id -> sp_code then lookup sp_code in csv and write to property
temp = OrderedDict()
with open("data/SP_SA_2011.json") as json_file:
    json_data = json.load(json_file)

    #iterate over jsondata and add properties by looking up spcode from csvdict
    for i in range(0,len(json_data['objects']['SP_SA_2011']['geometries']) -1):
        if(i % 500 == 0):
            print i,'/',len(json_data['objects']['SP_SA_2011']['geometries'])
        # need to set json_data['objects']['SP_SA_2011']['geometries'][i]['properties'] = tempdict at end...
        tempdict = json_data['objects']['SP_SA_2011']['geometries'][i]['properties']
        del tempdict['ALBERS_ARE']
        del tempdict['DC_MDB_C']
        del tempdict['DC_MN_C']
        del tempdict['DC_MN_C_st']
        del tempdict['MN_CODE']
        del tempdict['MN_CODE_st']
        del tempdict['MN_MDB_C']
        del tempdict['MP_CODE']
        del tempdict['PR_CODE']
        del tempdict['PR_MDB_C']
        del tempdict['SP_CODE_st']
        # look up properties to add
        spcode = tempdict['SP_CODE']
        # add new properties to tempdict
        for key in tempdict:
            newkey = key.decode('utf-8', 'ignore')
            tempdict2[newkey] = tempdict[key]
            if(type(tempdict[key]) is str):
                tempdict2[newkey] = tempdict[key].decode('utf-8', 'ignore')

        # write new properties to json_data
        json_data['objects']['SP_SA_2011']['geometries'][i]['properties'] = tempdict

    # write new topojson to file
    with io.open('data/sp_finaltopo.json', 'w', encoding='utf-8') as f:
        data = json.dumps(json_data, encoding='latin1')

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.