Generate List of all Features within a GDB

13188
5
Jump to solution
02-23-2015 06:51 AM
mpboyle
Occasional Contributor III

I'm looking for a way to generate one complete list of all feature classes within all feature datasets inside a gdb.

If I execute the script below, it generates multiple lists of feature classes for each dataset within the gdb.  Is there a way to combine each of these separate lists of feature classes into one complete list?

import arcpy

gdb = r"...path to some gdb"

arcpy.env.workspace = gdb

dsList = arcpy.ListDatasets("*", feature_type="Feature")
dsList.sort()
for ds in dsList:
    print ds

...list of datasets...

for ds in dsList:
    fcList = arcpy.ListFeatureClasses("*", feature_type="ALL", feature_dataset=ds)
    fcList.sort()
    print fcList

...separate lists of feature classes per feature dataset...

Thanks in advance!

0 Kudos
1 Solution

Accepted Solutions
JakeSkinner
Esri Esteemed Contributor

Hi Matthew,

Try the following:

fcList = []

for dataset in arcpy.ListDatasets():    
    for fc in arcpy.ListFeatureClasses("*", "ALL", dataset):
        fcList.append(fc)

for fc in arcpy.ListFeatureClasses():
    fcList.append(fc)

print fcList

View solution in original post

0 Kudos
5 Replies
JakeSkinner
Esri Esteemed Contributor

Hi Matthew,

Try the following:

fcList = []

for dataset in arcpy.ListDatasets():    
    for fc in arcpy.ListFeatureClasses("*", "ALL", dataset):
        fcList.append(fc)

for fc in arcpy.ListFeatureClasses():
    fcList.append(fc)

print fcList
0 Kudos
mpboyle
Occasional Contributor III

Thanks Jake Skinner‌.  That works!

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

The second code sample in the ArcGIS Help 10.2 - ListFeatureClasses (arcpy) gets you most of the way there.  The code below is adapted from the second code example:

import arcpy
import os

gdb = #
arcpy.env.workspace = gdb

datasets = arcpy.ListDatasets(feature_type='feature')
datasets = [''] + datasets if datasets is not None else []

fcList = []
for ds in datasets:
    for fc in arcpy.ListFeatureClasses(feature_dataset=ds):
        fcList.append(os.path.join(gdb, ds, fc))
        # fcList.append(os.path.join(ds, fc)) # if you don't want gdb path included
fcList.sort()

The Esri sample code, beyond providing the functional framework, incorporated two notable tips/ideas/practices.  The first is that including an empty string '' in the datasets list will allow the datasets loop to include the feature classes that aren't in a data set, i.e., the feature classes that are in the root/base of the geodatabase.

The second is that os.path.join is used to create the full path of the feature classes being listed.  If you are going to do any further processing of the list of feature classes, having the full path to them in the list makes the next steps easier.  Even if you are just listing feature classes to know what is present, including the data set along with the feature class will provide for more context.

RichardCrucchiola
New Contributor II

Having a bit of a unique problem with this code.  I used a bit of the code above to nest the ListFeatureClasses inside of the ListDatasets.  Under my ListFeatureClasses section I'm trying to use arcpy.Describe to extract the geometry storage type of the feature class.  I've hit a wall where if the feature class and the feature dataset have the exact same name my second for statement is closing out.

import os, arcpy, time
from time import clock, strftime, localtime

try:
    sdeConn = "Database Connections\\washsde_rlis_sde.sde"
    arcpy.env.workspace = sdeConn
    oFileHeaders = "FeatureDataset,FeatureClass,Geometry"
    oListTime = time.asctime()

    f = open("K:/Workgroups/GISITS/ADMIN_DBA_Projects/Binary2SQLGeometry/WashSDE_RLIS_fcGeom.csv", "w")
    f.write("SDE Connection: " + sdeConn + "\n")
    f.write("List Created On: " + oListTime + "\n")

    datasets = arcpy.ListDatasets(feature_type='feature')
    datasets = [''] + datasets if datasets is not None else []
    print datasets

    f.write('Datasets in geodatabase: ' + str(datasets) + "\n")
    f.write(oFileHeaders + "\n")

    for ds in datasets:
        for fc in arcpy.ListFeatureClasses(feature_dataset=ds):
            desc = arcpy.Describe(fc)
            vFile = desc.file
            vPath = desc.path
            vGeometry = desc.geometryStorage
            f.write(ds + "," + vFile + "," + vGeometry + "\n")
            print (ds + "," + vFile + "," + vGeometry)
    f.close()
except:
    print arcpy.GetMessage(1)
    print arcpy.GetMessage(arcpy.GetMessageCount() - 1)

I get a type 1 exception when its trying to deal with the RLIS.RLIS.boundary feature class in the similarly named RLIS.RLIS.BOUNDARY feature dataset.  The SDE instances is named RLIS and the database users is named RLIS.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

I find the original listing data functions (ListDatasets, ListFeatureClasses, ListFiles, etc...) rather clunky to work with compared to other options.  The ArcPy Walk function is good for finding or enumerating data sets.  In this case, though, since you are focused on specific geodatabases and want additional properties of data sets, like geometry storage type, I think the old Describe class is best.

The code below will go through a geodatabase and print out the data set names, types, and geometry storage if applicable.

import os

gdb = # path to geodatabase

full_path = False # Specify whether dataset name should be full or relative

desc = arcpy.Describe(gdb)
for child in desc.children:
    datasets = [child] + child.children
    for ds in datasets:
        print "{},{},{}".format(
            ds.catalogPath.replace("" if full_path else gdb + os.path.sep, ""),
            ds.datatype,
            ds.geometryStorage if hasattr(ds, "geometryStorage") else ""
        )