banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

#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

Yves
Membre du bureau
Lieu: Aix-les-Bains
Date d'inscription: 22 Mar 2006
Messages: 9864
Site web

Re: Fuite mémoire script python OGR

Bonjour,

Tu ne sauves jamais tes données outFeature ? (aucun rapport avec ta fuite mémoire wink )

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: 166

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

 

Pied de page des forums

Powered by FluxBB