6

Upgrading one of my GIS Python tool which uses GDAL/OGR to read vectors and rasters datasets, I've installed the last GDAL pypi package in version 2.1.3.

Until now, I do:

driver = ogr.GetDriverByName(str("ESRI Shapefile"))
source_ogr = driver.Open(shp_path, 0)
# or directly source_ogr = ogr.Open(shp_path, 0)
print(type(source_ogr))
>>> <class 'osgeo.ogr.DataSource'>

But when I checked the help, I see:

print(help(driver.Open))

[...]
NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned
handle to OGRDataSource*. If a C++ object is needed, the handle should
be cast to GDALDataset*. Similarly, the returned OGRSFDriverH handle
should be cast to GDALDriver*, and NOT* OGRSFDriver*.

Deprecated Use GDALOpenEx() in GDAL 2.0
[...]

And looking for more information, RFC 46 says:

A global pass has been made to in-tree OGR drivers that have to open a file to determine if they recognize it. They have been converted to GDALDriver to accept a GDALOpenInfo argument and they now use its pabyHeader field to examine the first bytes of files. The number of system calls realated to file access (open/stat), in order to determine that a file is not recognized by any OGR driver, has now dropped from 46 in GDAL 1.11 to 1. The converted drivers are : AeronavFAA, ArcGEN, AVCBin, AVCE00, BNA, CSV, DGN, EDIGEO, ESRI Shapefile, GeoJSON, GeoRSS, GML, GPKG, GPSBabel, GPX, GTM, HTF, ILI1, ILI2, KML, LIBKML, MapInfo? File, MySQL, NAS, NTF, OpenAIR, OSM, PDS, REC, S57, SDTS, SEGUKOOA, SEGY, SOSI, SQLite, SUA, SVG, TIGER, VFK, VRT, WFS

Indeed, using gdal.OpenEx it seems to work:

source_gdal = gdal.OpenEx(shp_path, 0)
pringt(type(source_gdal))
>>> <class 'osgeo.gdal.Dataset'>

And two objects are not identical:

print(source_ogr == source_gdal)
>>> False

Which method is better?

==== EDIT after first comments

# with OGR: note the GetName method
driver = ogr.GetDriverByName(str("OpenFileGDB"))
src = driver.Open(source_path, 0)
print(type(src), dir(src), len(dir(src)))
>>> <class 'osgeo.ogr.DataSource'> ['CommitTransaction', 'CopyLayer', 'CreateLayer', 'DeleteLayer', 'Dereference', 'Destroy', 'ExecuteSQL', 'FlushCache', 'GetDescription', 'GetDriver', 'GetLayer', 'GetLayerByIndex', 'GetLayerByName', 'GetLayerCount', 'GetMetadata', 'GetMetadataDomainList', 'GetMetadataItem', 'GetMetadata_Dict', 'GetMetadata_List', 'GetName', 'GetRefCount', 'GetStyleTable', 'GetSummaryRefCount', 'Reference', 'Release', 'ReleaseResultSet', 'RollbackTransaction', 'SetDescription', 'SetMetadata', 'SetMetadataItem', 'SetStyleTable', 'StartTransaction', 'SyncToDisk', 'TestCapability', '__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__len__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__swig_destroy__', '__weakref__', 'name', 'this', 'thisown'] 59


# with GDAL: note that the method list is different and GetName method is missing
src = gdal.OpenEx(source_path, 0)
print(type(src), dir(src), len(dir(src)))
>>> <class 'osgeo.gdal.Dataset'> ['AddBand', 'BeginAsyncReader', 'BuildOverviews', 'CommitTransaction', 'CopyLayer', 'CreateLayer', 'CreateMaskBand', 'DeleteLayer', 'EndAsyncReader', 'ExecuteSQL', 'FlushCache', 'GetDescription', 'GetDriver', 'GetFileList', 'GetGCPCount', 'GetGCPProjection', 'GetGCPs', 'GetGeoTransform', 'GetLayer', 'GetLayerByIndex', 'GetLayerByName', 'GetLayerCount', 'GetMetadata', 'GetMetadataDomainList', 'GetMetadataItem', 'GetMetadata_Dict', 'GetMetadata_List', 'GetProjection', 'GetProjectionRef', 'GetRasterBand', 'GetStyleTable', 'GetSubDatasets', 'GetTiledVirtualMem', 'GetTiledVirtualMemArray', 'GetVirtualMem', 'GetVirtualMemArray', 'RasterCount', 'RasterXSize', 'RasterYSize', 'ReadAsArray', 'ReadRaster', 'ReadRaster1', 'ReleaseResultSet', 'RollbackTransaction', 'SetDescription', 'SetGCPs', 'SetGeoTransform', 'SetMetadata', 'SetMetadataItem', 'SetProjection', 'SetStyleTable', 'StartTransaction', 'TestCapability', 'WriteRaster', '__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__swig_destroy__', '__weakref__', 'this', 'thisown'] 76
2

1 Answer 1

4

In GDAL 2 the OGRDatasource was merged with GDALDataset.

Traditionally GDAL used to design the raster part of the library, and OGR the vector part for Simple Features. Starting with GDAL 2.0, both sides have been more tightly integrated

And now all classes inherited from one class - GDALDataset. The OpenEx is preferable to use in GDAL 2 and higher versions. The different between source_ogr and source_gdal is because python binding features.

3
  • So, I decided to use the new way but things are not so similar between OGR or GDAL openers. I edit my question to include details.
    – Guts
    Mar 9, 2017 at 10:17
  • What's the reasoning behind the Ex suffix? Why not add the same functionality to the normal Open call. Also what about OpenShared? Jul 11, 2017 at 9:46
  • Backward compatibility. The count of input parameters differs and old software will crash if it use new GDAL with modified Open method. Jul 11, 2017 at 12:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.