8

I'm writing a shapefile using OGR in python, creating fields on-the-fly from a python data source. Creation of a new field requires an OGR data type, is there a mapping between OGR and python data types?

For example, this would be the norm:

new_field = ogr.FieldDefn('MYFLD', ogr.OFTInteger)

Ideally:

ogr_datatype = get_ogr_data_type(python_data)
new_field = ogr.FieldDefn('MYFLD', ogr_datatype)

Currently my conversions are hard coded (e.g. int = ogr.OFTInteger), but this is a bit of a pain and relies on me coding all possible data types.

1
  • I think the geodjango ogr wrapper is the best wrapper I've ever used. It provides a very intuitive way to describe geo features. You could find more information about it in geodjango website.
    – xiao
    Jan 31, 2012 at 8:45

3 Answers 3

9

You'll have to create a dictionary of Python types to OGR "types" because they're just ints. It's a bit of a pain I grant you, but OGR (and the SWIG-generated bindings) have no notion of a language's types whether it's in C or Python.

Something like this should work:

OGRTypes = {int: ogr.OFTInteger, str: ogr.OFTString, ...}

...

new_field = ogr.FieldDefn('MYFLD', OGRTypes[type(python_data)])
0
8

For what it's worth, I've got a Python package that contains such a mapping. See https://github.com/Toblerity/Fiona/blob/master/src/fiona/ogrext.pyx#L18. Copied here:

# Mapping of OGR integer field types to Fiona field type names.
#
# Only ints, floats, and unicode strings are supported. On the web, dates and
# times are represented as strings (see RFC 3339). 
FIELD_TYPES = [
    'int',          # OFTInteger, Simple 32bit integer
    None,           # OFTIntegerList, List of 32bit integers
    'float',       # OFTReal, Double Precision floating point
    None,           # OFTRealList, List of doubles
    'str',          # OFTString, String of ASCII chars
    None,           # OFTStringList, Array of strings
    None,           # OFTWideString, deprecated
    None,           # OFTWideStringList, deprecated
    None,           # OFTBinary, Raw Binary data
    None,           # OFTDate, Date
    None,           # OFTTime, Time
    None,           # OFTDateTime, Date and Time
    ]

# Mapping of Fiona field type names to Python types.
FIELD_TYPES_MAP = {
    'int':      IntType,
    'float':    FloatType,
    'str':      UnicodeType,
    }

My mapping is incomplete because I don't run into many OFT*List fields in the wild. You'd want to map these to Python arrays, I suppose (OFTIntegerList -> array('i') for example) since Python's lists aren't typed. OFTDate/Time fields are the devil and mapping these to Python DateTime doesn't make the situation any better because the datetime module API is awful. In my project, I'm going to map dates and times to ISO 8601 strings like "2012-01-02T20:59:38Z". Raw binary data would be mapped to a non-unicode Python string (which becomes the bytes type in Python 3).

1
  • Was going to mention fiona and then I scroll down and see you have already posted :)
    – Nathan W
    Jan 12, 2012 at 11:35
1

If you're goal is simply shapefile editing in Python check out PyShp:

http://code.google.com/p/pyshp/

It's pure python so you only use python data types. I also have examples of common geometry and attribute operations on GeospatialPython.com

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.