24

From python how can I build a list of all feature classes in a file geodatabase (*.gdb), including inside feature datasets? The standard example only lists feature classes at the top level of the geodatabase:

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

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

for fc in fcs:
    print fc

Please indicate which ArcGIS Desktop version your answer applies to (I am looking for 9.3 but we might as well collect all versions in one place).

34

This routine for arcgis10 returns all fcs (standalone OR within a feature dataset) inside a gdb. Just set your arcpy.env.workspace then do a for loop

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)
  • Nice and clean! – Chad Cooper Feb 8 '11 at 19:10
  • 1
    thanks gotchula! That's the first time I've encountered the yield statement, had to do a bit of reading to figure it out. You forgot to note your sample is for arcgis v10. – matt wilkie Feb 8 '11 at 22:28
  • 1
    sorry, yeah this is for 10.x. and yes, the yield is great, makes for clean code. – gotchula Feb 8 '11 at 23:09
  • Thanks gotchula, I know this is an old post but I just found this very helpful for managing a database I add to every week. Could I ask you what the + [' ']: accomplishes in the 3rd line? – Dylan Warburg Jan 22 '18 at 19:09
  • 1
    i call arcpy.ListFeatureClasses inside a loop of arcpy.ListDatasets. I need to include the featureclasses which are NOT inside any feature dataset (aka standalone feature class), so I add '' to the list of datasets which causes ListFeatureClasses to get called with '' as the fds variable. – gotchula Feb 27 '18 at 22:51
12

I ended up using gotchula's answer, but without yield because I generally re-use the FC handles created and yield's are used once then discarded it's easier for me to read and understand what fcs.append() is doing than 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            

Results:

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
...

This is now in a module I call arcplus*. Place with your other code or PYTHONPATH and then:

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

Arcplus also adds wildcard filtering; to process only feature classes that start with "HD_" within feature datasets containing "Hydro"

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

.* now on Github, upgraded for 10.x. For arcgis 9.3 see here.

  • 1
    Not sure I understand the rationale behind avoiding use of yield here. For one, the "handles" you refer to are not handles at all, they're just strings. And if your intention is to keep the list of feature classes around for multiple iterations, you can still keep it as a generator function and just "listify" it: my_list = list(generator_function(args)) this evaluates the generator and stores the result in a list variable. – blah238 May 22 '14 at 19:39
  • @blah238: oh. I guess I still don't grok yield then. I understand what a statement like fcs = fcs.append(...) is doing much more quickly than fcs = list(yield(...)). – matt wilkie May 26 '14 at 18:07
8

I realise this question is tagged 9.3, but anyone looking for the same answer at 10.1 onwards is better off using arcpy.da.Walk. It is faster and more accurate than 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)

The walk function works in the same way as python's walk. It iterates through the directories in the given path and at each iteration, root represents the full path of the directory, and dirs and datasets are lists of the subdirectories and files contained within.

When walking through a geodatabase, feature datasets are treated in the same way as directories. If you only want to list the datasets and feature datasets in the root folder and not open up the feature datasets to see the contents, you can do:

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
  • I'll take faster as a given; can you expand on "more accurate" though? Thanks. – matt wilkie May 13 '16 at 17:56
  • ListDatasets, ListFeatureClasses, etc. don't always return the correct datasets. Also, you get different results between SDE and file GDB. I can't remember the exact issue, but we stopped using arcpy.List... because we couldn't trust the results. – jon_two May 16 '16 at 12:13
5

The ListDatasets method is what I think you are looking for. This FGDB has a FD in it called "Wells" and it has 3 FCs in it. For 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
>>>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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