Répertorier toutes les classes d'entités dans la géodatabase fichier, y compris dans les jeux de données d'entités?

24

À partir de python, comment puis-je créer une liste de toutes les classes d'entités dans une géodatabase fichier (* .gdb), y compris à l'intérieur des jeux de données d'entités? L' exemple standard répertorie uniquement les classes d'entités au niveau supérieur de la géodatabase:

import arcgisscripting, os
gp = arcgisscripting.create(9.3)

gp.workspace = 'd:\scratch.gdb'
fcs = gp.ListFeatureClasses()

for fc in fcs:
    print fc

Veuillez indiquer à quelle version d'ArcGIS Desktop votre réponse s'applique (je recherche 9.3 mais nous pourrions aussi bien rassembler toutes les versions en un seul endroit).

Matt Wilkie
la source
1
Un Q&R connexe mais plus à jour (y compris l'utilisation de arcpy.da.Walk) est Comment faire un inventaire SIG?
blah238

Réponses:

34

Cette routine pour arcgis10 renvoie tous les fcs (OU autonomes dans un jeu de données d'entité) à l'intérieur d'une gdb. Définissez simplement votre arcpy.env.workspace puis faites une boucle for

def listFcsInGDB():
    ''' set your arcpy.env.workspace to a gdb before calling '''
    for fds in arcpy.ListDatasets('','feature') + ['']:
        for fc in arcpy.ListFeatureClasses('','',fds):
            yield os.path.join(arcpy.env.workspace, fds, fc)
gotchula
la source
Agréable et propre!
Chad Cooper
1
merci gotchula! C'est la première fois que je rencontre l'énoncé de rendement, j'ai dû faire un peu de lecture pour le comprendre. Vous avez oublié de noter que votre échantillon est pour arcgis v10.
matt wilkie
1
désolé, oui c'est pour 10.x. et oui, le rendement est excellent, rend le code propre.
gotchula
Merci gotchula, je sais que c'est un ancien article mais je l'ai trouvé très utile pour gérer une base de données à laquelle j'ajoute chaque semaine. Puis-je vous demander ce que le + ['']: accomplit dans la 3ème ligne?
Dylan Warburg
1
j'appelle arcpy.ListFeatureClasses à l'intérieur d'une boucle d'arcpy.ListDatasets. Je dois inclure les featureclasses qui ne sont PAS dans un jeu de données d'entité (aka classe d'entités autonome), donc j'ajoute '' à la liste des jeux de données, ce qui provoque l'appel de ListFeatureClasses avec '' comme variable fds.
gotchula
12

J'ai fini par utiliser la réponse de gotchula , mais sans rendement car je réutilise généralement les poignées FC créées et les rendements sont utilisés une fois puis jetés, il est plus facile pour moi de lire et de comprendre ce qui fcs.append()se passe que fcs = yield(...).

def listFcsInGDB(gdb):
    ''' list all Feature Classes in a geodatabase, including inside Feature Datasets '''
    arcpy.env.workspace = gdb
    print 'Processing ', arcpy.env.workspace

    fcs = []
    for fds in arcpy.ListDatasets('','feature') + ['']:
        for fc in arcpy.ListFeatureClasses('','',fds):
            #yield os.path.join(fds, fc)
            fcs.append(os.path.join(fds, fc))
    return fcs

gdb = sys.argv [1]
fcs = listFcsInGDB(gdb)
for fc in fcs:
    print fc            

Résultats:

d:\> python list-all-fc.py r:\v5\YT_Canvec.gdb
Processing  r:\v5\YT_Canvec.gdb
Buildings_and_structures\BS_2530009_0
Buildings_and_structures\BS_2380009_2
Buildings_and_structures\Tower
Buildings_and_structures\Underground_reservoir
...

C'est maintenant dans un module que j'appelle arcplus *. Placez avec votre autre code ou PYTHONPATH puis:

import arcplus
fcs = arcplus.listAllFeatureClasses('d:\default.gdb')
for fc in fcs:
    print "magic happens with: ", fc

Arcplus ajoute également un filtrage générique; pour traiter uniquement les classes d'entités commençant par "HD_" dans les jeux de données d'entité contenant "Hydro"

fcs = arcplus.listAllFeatureClasses(gdb, fd_filter='*Hydro*', fc_filter='HD_*')

. * maintenant sur Github, mis à niveau pour 10.x. Pour arcgis 9.3, voir ici .

Matt Wilkie
la source
1
Je ne suis pas sûr de comprendre la raison pour laquelle vous évitez d'utiliser yieldici. D'une part, les «poignées» auxquelles vous faites référence ne sont pas du tout des poignées, ce ne sont que des chaînes. Et si votre intention est de conserver la liste des classes d'entités pour plusieurs itérations, vous pouvez toujours la conserver en tant que fonction de générateur et simplement la «lister»: my_list = list(generator_function(args))cela évalue le générateur et stocke le résultat dans une variable de liste.
blah238
@ blah238: oh. Je suppose que je ne fais toujours pas de rendement alors. Je comprends ce que fait une déclaration fcs = fcs.append(...)beaucoup plus rapidement que fcs = list(yield(...)).
matt wilkie
8

Je me rends compte que cette question est étiquetée 9.3, mais quiconque cherche la même réponse à partir de 10.1 est préférable d'utiliser arcpy.da.Walk . Il est plus rapide et plus précis que ListDatasets / FeatureClasses / Rasters / etc.

import arcpy
import os

for root, dirs, datasets in arcpy.da.Walk('d:\scratch.gdb'):
    for ds in datasets:
        print os.path.join(root, ds)

La fonction de marche fonctionne de la même manière que la marche de python . Il parcourt les répertoires dans le chemin donné et à chaque itération, root représente le chemin complet du répertoire, et les répertoires et les jeux de données sont des listes des sous-répertoires et des fichiers qu'il contient.

Lorsque vous parcourez une géodatabase, les jeux de données d'entité sont traités de la même manière que les répertoires. Si vous souhaitez uniquement répertorier les jeux de données et les jeux de données d'entité dans le dossier racine et ne pas ouvrir les jeux de données d'entité pour voir le contenu, vous pouvez faire:

for root, dirs, datasets in arcpy.da.Walk('d:\scratch.gdb'):
    print 'feature datasets:'
    for fds in dirs:
        print os.path.join(root, fds)
    print 'datasets:'
    for ds in datasets:
        print os.path.join(root, ds)
    break
jon_two
la source
Je vais prendre plus vite comme une donnée; pouvez-vous développer "plus précis"? Merci.
matt wilkie
ListDatasets, ListFeatureClasses, etc. ne renvoient pas toujours les jeux de données corrects. En outre, vous obtenez des résultats différents entre SDE et le fichier GDB. Je ne me souviens pas du problème exact, mais nous avons cessé d'utiliser arcpy.List ... car nous ne pouvions pas faire confiance aux résultats.
jon_two
5

La ListDatasets méthode est ce que je pense que vous recherchez. Ce FGDB contient un FD appelé "Wells" et il contient 3 FC. Pour 9.3.1:

C:\WINDOWS\system32>python
Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import arcgisscripting
>>> gp=arcgisscripting.create(9.3)
>>> d='c:\data\Third_Party_Wells_PRD.gdb'
>>> gp.workspace = d
>>>
>>> fds=gp.ListDatasets('','Feature')
>>> for fd in fds:
...     print fd
...
Wells
>>> for fd in fds:
...     gp.workspace=d + '/' + fd
...     fcs=gp.ListFeatureClasses()
...     for fc in fcs:
...             print fc
...
Third_Party_Wells_BHL
Third_Party_Wells_LAT
Third_Party_Wells_SHL
>>>
Chad Cooper
la source