Select to view content in your preferred language

ValidateTableName function

180
2
Jump to solution
4 weeks ago
Trans-TelCentral
New Contributor

Hello, I am relatively new to Python scripting, and trying to automate a task at work. Basically, the script is supposed to copy a shape file [named 'backbone'] from the env.workspace into the specified file GDB. The script works fine, but I am trying to run this script numerous times by changing the env.workspace and re-running the script. 

With that being said, if there was a feature class in the file GDB already named 'backbone', the original script would copy the new one over the original. I thought that arcpy.ValidateName() was the function used to prevent this from happening, and it would rename the new feature class so the original would not be written over; is this a misconception on my end?

After some trial and error, I was able to add a nested if statement that checked for a feature class named 'backbone', and if true, would add a '1' to the end of the new feature class's name. Here lies the problem: if I change the env.workspace to another file location, it will just restart my counter variable and overwrite 'backbone1'. I'm sure the solution is simple, just beyond my elementary knowledge base; any help would be greatly appreciated! I have copy and pasted the script below:

import arcpy
from arcpy import env

env.overwriteOutput = True
env.workspace = 'C:/Users/MWright/Downloads/YaleToSC/'
outputEnv = 'M:/Drafting/IECcoop/PhaseIII/PawneeToYale/PawneeToYales.gdb/'
x = 'backbone'
count = 1

fclist = arcpy.ListFeatureClasses()
print(fclist)
print('\n')

for fc in fclist:
   fcdesc = arcpy.Describe(fc)
   fcname = fcdesc.basename
   if fcname == 'backbone':
      if arcpy.Exists(x):
         fcout = arcpy.ValidateTableName(fcname, outputEnv)
         arcpy.CopyFeatures_management(fc, outputEnv + fcout + str(x))

         print('\n' + fcname + ' has been copied to GDB.\n')
         x += 1
      else:
         fcout = arcpy.ValidateTableName(fcname, outputEnv)
         arcpy.CopyFeatures_management(fc, outputEnv + fcout + str(count))
   else:
      print(fcname + " feature class does not need to be copied to geodatabase.")

print('\nBackbone feature class copy process complete.')

 

0 Kudos
1 Solution

Accepted Solutions
HaydenWelch
Occasional Contributor II

You're really close, you just need to store the index in the feature names themselves:

 

 

import arcpy
from arcpy import env

env.overwriteOutput = True
env.workspace = 'C:/Users/MWright/Downloads/YaleToSC/'
outputEnv = 'M:/Drafting/IECcoop/PhaseIII/PawneeToYale/PawneeToYales.gdb/'
outName = 'backbone'

fclist = arcpy.ListFeatureClasses()

print(fclist)
print('\n')

# Iterate FCs in workspace (YaleToSC)
for fc in fclist:
   fcdesc = arcpy.Describe(fc)
   fcname = fcdesc.basename
   
   # Check if the FC name contains the substring 'backbone'
   if 'backbone' in fcname:
      # Split the FC name into a list of substrings separated by '_', Use *_ to consume any additional substrings beyond the first 2
      # Add None to end of list to prevent ValueError if the FC name does not contain '_' and the list has only 1 element
      name, index, *_ = fcname.split('_') + [None]
      
      # If the name is just 'backbone', initialize the index to 1
      if name == 'backbone' and not index:
         arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_1")
      
      # If the name is 'backbone' followed by a number, increment the number by 1
      elif index and index.isdigit():
         arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_{int(index) + 1}")
         
   # Ignore all non-backbone feature classes
   else:
      print(f'{fcname} is not a backbone feature class.')
      
print('\nBackbone feature class copy process complete.')

 

Here's a version that runs as a script and takes a list of workspaces:

import arcpy
from arcpy import env

# Iterate FCs in workspace (YaleToSC)

def copy_backbone(outputEnv, outName, fclist):
    for fc in fclist:
       fcdesc = arcpy.Describe(fc)
       fcname = fcdesc.basename
   
   # Check if the FC name contains the substring 'backbone'
       if 'backbone' in fcname:
      # Split the FC name into a list of substrings separated by '_', Use *_ to consume any additional substrings beyond the first 2
      # Add None to end of list to prevent ValueError if the FC name does not contain '_' and the list has only 1 element
          name, index, *_ = fcname.split('_') + [None]
      
      # If the name is just 'backbone', initialize the index to 1
          if name == 'backbone' and not index:
             arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_1")
      
      # If the name is 'backbone' followed by a number, increment the number by 1
          elif index and index.isdigit():
             arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_{int(index) + 1}")
         
   # Ignore all non-backbone feature classes
       else:
          print(f'{fcname} is not a backbone feature class.')

def main():
   env.overwriteOutput = True
   outputEnv = 'M:/Drafting/IECcoop/PhaseIII/PawneeToYale/PawneeToYales.gdb/'
   outName = 'backbone'
   workspaces = ['C:/Users/MWright/Downloads/YaleToSC/', '<wsp1>', '<wsp2>', ...]
   
   for workspace in workspaces:
      env.workspace = workspace
      fclist = arcpy.ListFeatureClasses()
      print(f'Processing {workspace}...')
      print(f'Feature classes in {workspace}: {fclist}')
      copy_backbone(outputEnv, outName, fclist)

   print('\nBackbone feature class copy process complete.')

if __name__ == '__main__':
   main()

View solution in original post

0 Kudos
2 Replies
HaydenWelch
Occasional Contributor II

You're really close, you just need to store the index in the feature names themselves:

 

 

import arcpy
from arcpy import env

env.overwriteOutput = True
env.workspace = 'C:/Users/MWright/Downloads/YaleToSC/'
outputEnv = 'M:/Drafting/IECcoop/PhaseIII/PawneeToYale/PawneeToYales.gdb/'
outName = 'backbone'

fclist = arcpy.ListFeatureClasses()

print(fclist)
print('\n')

# Iterate FCs in workspace (YaleToSC)
for fc in fclist:
   fcdesc = arcpy.Describe(fc)
   fcname = fcdesc.basename
   
   # Check if the FC name contains the substring 'backbone'
   if 'backbone' in fcname:
      # Split the FC name into a list of substrings separated by '_', Use *_ to consume any additional substrings beyond the first 2
      # Add None to end of list to prevent ValueError if the FC name does not contain '_' and the list has only 1 element
      name, index, *_ = fcname.split('_') + [None]
      
      # If the name is just 'backbone', initialize the index to 1
      if name == 'backbone' and not index:
         arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_1")
      
      # If the name is 'backbone' followed by a number, increment the number by 1
      elif index and index.isdigit():
         arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_{int(index) + 1}")
         
   # Ignore all non-backbone feature classes
   else:
      print(f'{fcname} is not a backbone feature class.')
      
print('\nBackbone feature class copy process complete.')

 

Here's a version that runs as a script and takes a list of workspaces:

import arcpy
from arcpy import env

# Iterate FCs in workspace (YaleToSC)

def copy_backbone(outputEnv, outName, fclist):
    for fc in fclist:
       fcdesc = arcpy.Describe(fc)
       fcname = fcdesc.basename
   
   # Check if the FC name contains the substring 'backbone'
       if 'backbone' in fcname:
      # Split the FC name into a list of substrings separated by '_', Use *_ to consume any additional substrings beyond the first 2
      # Add None to end of list to prevent ValueError if the FC name does not contain '_' and the list has only 1 element
          name, index, *_ = fcname.split('_') + [None]
      
      # If the name is just 'backbone', initialize the index to 1
          if name == 'backbone' and not index:
             arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_1")
      
      # If the name is 'backbone' followed by a number, increment the number by 1
          elif index and index.isdigit():
             arcpy.CopyFeatures_management(fc, f"{outputEnv}{outName}_{int(index) + 1}")
         
   # Ignore all non-backbone feature classes
       else:
          print(f'{fcname} is not a backbone feature class.')

def main():
   env.overwriteOutput = True
   outputEnv = 'M:/Drafting/IECcoop/PhaseIII/PawneeToYale/PawneeToYales.gdb/'
   outName = 'backbone'
   workspaces = ['C:/Users/MWright/Downloads/YaleToSC/', '<wsp1>', '<wsp2>', ...]
   
   for workspace in workspaces:
      env.workspace = workspace
      fclist = arcpy.ListFeatureClasses()
      print(f'Processing {workspace}...')
      print(f'Feature classes in {workspace}: {fclist}')
      copy_backbone(outputEnv, outName, fclist)

   print('\nBackbone feature class copy process complete.')

if __name__ == '__main__':
   main()
0 Kudos
Trans-TelCentral
New Contributor

This helps so much - thanks for pointing me in the right direction!

0 Kudos