#1 Tue 23 February 2010 17:49
- dominique.lys
- Participant assidu
- Date d'inscription: 5 Oct 2006
- Messages: 473
- Site web
Fuite mémoire script python OGR
Bonjour,
Travaillant sous ArcGIS, je dois régulièrement réaliser des buffers sur des couches très lourdes. Malheureusement l'outil buffer d'ArcGIS supporte mal mes données et plante une fois sur deux.
Pour pallier à ce problème j'ai rédigé un script python utilisant OGR en m'inspirant de ces excellents tutoriels.
Le script fonctionne et OGR semble assez robuste mais l'utilisation mémoire d'ArcGIS ne cesse d'augmenter or comme je boucle ma fonction sur plusieurs couches au bout d'un moment ça plante.
Voici le code:
Code:
# -*- coding:Latin-1 -*- import osgeo.ogr, os, sys, string # function to copy fields (not the data) from one layer to another # parameters: # fromLayer: layer object that contains the fields to copy # toLayer: layer object to copy the fields into def copyFields(fromLayer, toLayer): featureDefn = fromLayer.GetLayerDefn() for i in range(featureDefn.GetFieldCount()): toLayer.CreateField(featureDefn.GetFieldDefn(i)) # function to copy attributes from one feature to another # (this assumes the features have the same attribute fields!) # parameters: # fromFeature: feature object that contains the data to copy # toFeature: feature object that the data is to be copied into def copyAttributes(fromFeature, toFeature): for i in range(fromFeature.GetFieldCount()): fieldName = fromFeature.GetFieldDefnRef(i).GetName() toFeature.SetField(fieldName, fromFeature.GetField(fieldName)) def doBuffers(inShp, outShp, filtre, taille, proj): # get the shapefile driver driver = osgeo.ogr.GetDriverByName('ESRI Shapefile') # open.shp and get the layer shp = driver.Open(inShp, 0) if shp is None: return 0 inLayer = shp.GetLayer() # create a new data source and layer if os.path.exists(outShp): driver.DeleteDataSource(outShp) outDS = driver.CreateDataSource(outShp) outLayer = outDS.CreateLayer(outShp, geom_type=osgeo.ogr.wkbPolygon, srs=proj) # copy the fields from the input layer to the output layer copyFields(inLayer, outLayer) # get the FeatureDefn for the output shapefile featureDefn = outLayer.GetLayerDefn() # use an attribute filter inLayer.SetAttributeFilter(filtre) # get features inFeature = inLayer.GetNextFeature() while inFeature: # get the geometry and buffer it inGeom = inFeature.GetGeometryRef() bufferGeom = inGeom.Buffer(taille) # create a new feature outFeature = osgeo.ogr.Feature(featureDefn) # set the geometry and attribute outFeature.SetGeometry(bufferGeom) # copy the attributes copyAttributes(inFeature, outFeature) # add the feature to the shapefile outLayer.CreateFeature(outFeature) # destroy the features and get the next input feature outFeature.Destroy() inFeature.Destroy() #Destroy test #inGeom.Destroy() #Do not destroy geometries that come from an existing feature Python will crash bufferGeom.Destroy() #Do destroy geometries that are created during script execution (even if they are during script execution (even if they are used to create new features) # get next feature inFeature = inLayer.GetNextFeature() # close the shapefiles outDS.Destroy() shp.Destroy() return 1
Je ne vois pas trop d'où proviens la fuite, donc si quelqu'un aurait une suggestion!
Hors ligne
#2 Tue 23 February 2010 19:59
Re: Fuite mémoire script python OGR
Bonjour,
Tu ne sauves jamais tes données outFeature ? (aucun rapport avec ta fuite mémoire )
Y.
Yves Jacolin, bénévole de l'association GeoRezo.net, agit au nom et pour le compte de l'association - Partageons ce qui nous départage !! - GeoRezo vous aide ? Aidez GeoRezo !
Hors ligne
#3 Tue 23 February 2010 21:54
- dominique.lys
- Participant assidu
- Date d'inscription: 5 Oct 2006
- Messages: 473
- Site web
Re: Fuite mémoire script python OGR
Code:
outDS = driver.CreateDataSource(outShp) outLayer = outDS.CreateLayer(outShp, geom_type=osgeo.ogr.wkbPolygon, srs=proj)
Ces deux lignes permettent de créer un shape vierge
Code:
featureDefn = outLayer.GetLayerDefn() outFeature = osgeo.ogr.Feature(featureDefn) outFeature.SetGeometry(bufferGeom)
Ici on créé un nouvel objet que l'on pourra insérer dans le shape
Code:
outLayer.CreateFeature(outFeature)
D'ailleurs ici on insère l'objet en dur dans le shape
Code:
outDS.Destroy()
Ensuite on ferme proprement le shape qui contient à présent tous les objets précédemment insérés. Et effectivement en ouvrant le shape on retrouve nos buffers.
Trouvant la remarque pertinente, j'ai vérifier les exemples sus cités et à aucun moment le shape n'est explicitement sauvé.
Hors ligne
#4 Tue 23 February 2010 22:36
- rouault
- Participant assidu
- Date d'inscription: 26 Apr 2009
- Messages: 168
Re: Fuite mémoire script python OGR
Ton script python est parfait. outDS.Destroy() suffit à fermer et sauvegarder le fichier comme il faut.
2 hypothèses :
1) tu utilises une version de GDAL qui aurait des fuites mémoires au niveau du binding Python, mais je n'y crois pas trop a priori. Essaye tout de même avec la dernière version de GDAL
2) j'ai fait quelques essais et j'ai constaté que l'algorithme Buffer() de GEOS (la librairie utilisée pour faire le boulot) peut consommer énormément de mémoire sur certaines géométries très complexes. Il ne s'agit cependant pas vraiment de fuite mémoire a proprement dit.
Hors ligne
#5 Tue 23 February 2010 23:13
- dominique.lys
- Participant assidu
- Date d'inscription: 5 Oct 2006
- Messages: 473
- Site web
Re: Fuite mémoire script python OGR
Ce qui me laisse supposer qu'il y a un problème c'est qu'en démarrant ArcGIS j'ai une utilisation mémoire de 40mo alors qu'après exécution du script je me retrouve à 800mo; c'est bien que toutes les allocations mémoire n'ont pas été détruites.
Je soupçonne que ce soit l'objet "inGeom" l'origine du soucis, pourtant comme la variable est réaffectée à chaque passage dans la boucle le garbage collector devrait faire son boulot. De toute façon il n'est pas possible de forcer la destruction de cet objet car ça provoque un plantage de python.
J'essaierai demain d'upgrader GDAL (1.6-->1.7).
Hors ligne
#6 Thu 04 March 2010 09:51
- dominique.lys
- Participant assidu
- Date d'inscription: 5 Oct 2006
- Messages: 473
- Site web
Re: Fuite mémoire script python OGR
Pour le suivi, j'ai résolu mon soucis en passant à la version 1.7 ! Le problème venait donc du binding et non du script.
Hors ligne