3

I am a novice in python programming but I am trying to learn by doing.

I got stuck with this function a while back and can't seem to find a solution or a workaround.

I am writing a script that is trying to select all data in an MXD within a 70m distance from a layer and then export that data to a newly created file geodatabase. I can ́t seem to get this to work, all I get is the error:

FDO error: -2147024894 [GDB_Items]
The table was not found. [Output name]

And I somehow manage to get some kind of output, in the form of empty geodatabase tables in the output file geodatabase with the "correct" output names.

I have a suspicion that the problem lies in the feature layers origins. They reside deep in our file tree (for exampel G:\KONSULTUPPDRAG VMN\SAMRÅD2012円\Uppsala\C 55 Örsundsbro - Kvarnbo\Kartor\Grundkartor\Fastighetskartan.gdb\vo) there is nothing I can do about it unfortunately.

Here is my code:

import arcpy, os, re
from unicodedata import normalize
Skapa_mapp = (unicode ("C:\\Users\dabr\\Desktop\KMZtest\\", 'UTF-8'))
Mxd_Natur = arcpy.mapping.MapDocument((unicode ("C:\\Users\\dabr\\Desktop\\KMZ test\\YAYYY_Test1.mxd", 'UTF-8')))
Vag = "c 801"
def Select_and_Export (Mxd_Natur, Skapa_mapp, Vag):
 Db = Skapa_mapp +"KMZ\\KMZ_Databas.gdb\\" #Define the output DB
for df in arcpy.mapping.ListDataFrames(Mxd_Natur): #Find the road from whitch the selection is made with. 
 for lyr in arcpy.mapping.ListLayers(Mxd_Natur, "", df):
 if lyr.name.lower() == unicode (Vag, 'UTF-8'):
 Utgangslager = lyr
for df in arcpy.mapping.ListDataFrames(Mxd_Natur): 
 for lyr in arcpy.mapping.ListLayers(Mxd_Natur, "", df): #Loop trough all the layers in the MXD to make 
 #a selection and exprt if annything got selected
 Sokvag = lyr.workspacePath #Get the path to the specific layer
 SokvagNamn = lyr.datasetName #Get the name of the specific layer
 File_path = Sokvag + "\\" + SokvagNamn #Combine to create full path
 print File_path
 if not Sokvag.endswith(".gdb"): #layers in mxd can be both from GDB and .shp
 File_path = File_path + ".shp"
 Namn = lyr.name.lower() # 
 Namn = re.sub('[ ]', '_', Namn) #create a output name bades on the layer name 
 Namn = normalize('NFKD', Namn).encode('ascii', 'ignore') #in the mxd
 if arcpy.Exists("TEMP"): #if temporary file exis ́ts from previous run, remove it
 arcpy.Delete_management("TEMP")
 print "temp removed"
 arcpy.management.MakeFeatureLayer(File_path,"TEMP") #Recreata a empty templayer
 arcpy.SelectLayerByLocation_management("TEMP", "WITHIN_A_DISTANCE", Utgangslager, "70 Meters", "NEW_SELECTION") #populate the templayer whit selected objekts?
 out = os.path.join(Db, Namn) #Create a path to the output location
 print str(arcpy.GetCount_management("TEMP").getOutput(0))+" Selected from " + Namn #Show number of selected objekts.
 if int(arcpy.GetCount_management("TEMP").getOutput(0)) > 0: #check if anny objects were selected. if not dont export
 try:
 if "TEMP".endswith(".shp"): #test if the temporary layer is based on a shp file?
 print Namn + " skall shp kopieras"
 arcpy.CopyFeatures_management("TEMP", out.rstrip(".shp")) #Coppy selected objekts to FDB
 print Namn + " shp kopierad"
 else:
 print Namn + " skall koppiers"
 arcpy.CopyFeatures_management("TEMP", out) #Coppy selected objekts to FDB
 print Namn + " är kopierad"
 except:
 print arcpy.GetMessages()
 else:
 print lyr.name.lower() + " no objekts were selected"

Does anyone see a solution to my problem or perhaps a workaround?

Edit: After some tweaking I stumbled upon the problem and solution. I was using a File GDB as an output in the CopyFeatures_management function. I don’t know why but if I changed it to a personal GDB everything went fine. Can anyone explain why?

Fezter
22k11 gold badges72 silver badges128 bronze badges
asked Nov 9, 2012 at 12:03
4
  • 2
    One thing to try is to turn your strings into raw-strings and remove the double backslash so that "C:\Users\dabr\Desktop\KMZtest\\" becomes r"C:\Users\dabr\Desktop\KMZtest\". The backslash character, "\", is used to escape characters that have special meaning, e.g. "\n" is a newline character, "\t" is a tab character, etc. You can remove the ambiguity in your code by converting your strings to raw-strings as mentioned above, using a forward slash "/" (does not have to be converted to a raw string), or by using the double backslash "\\" everywhere. Commented Nov 9, 2012 at 13:52
  • I went whit the "double backslash \\", this had no direct effect on the outcome. But thanks for helping me write my code better Commented Nov 9, 2012 at 14:51
  • 1
    Sure thing; I usually go with the raw-strings just because it's easier to copy and paste paths from Explorer and add the 'r' to it. Sorry I can't be of more help to you. Commented Nov 9, 2012 at 15:01
  • True, that sounds like a good reason, but sins haven’t gotten the hang of \n,\t,\r and all the rest I´ll play it safe and go with what I know for now. I appreciate you taking the time. Commented Nov 9, 2012 at 15:18

2 Answers 2

1

I wonder if this will help?

replace the following line,

if "TEMP".endswith(".shp"):

with this line

if arcpy.Describe("TEMP").featureClass.catalogPath.endswith(".shp"): 
urcm
22.6k4 gold badges59 silver badges109 bronze badges
answered Nov 10, 2012 at 14:43
0
0

You will need to work back in some of your logic. Mostly the naming of your tables and the select by location. My map is using very simple names. If you have trouble post some of the layer names in the map and I can test using those. You will also need to put back in your mxd and file paths.

This code needs to be cleaned up and you should read into better error checking than I am using. Let me know if you have any questions.

import arcpy, os, re
from random import randint
skapa_mapp = (r"C:\Users\ajones\Documents\ArcGIS")
input_mxd = arcpy.mapping.MapDocument(r"C:\Users\ajones\Documents\ArcGIS\tempProjectData\arcpy_mapping.mxd")
vag = "Export_Output_4" # - c 801
db_path = "tempProjectData" # - KMZ
db_name ="superTemp.mdb" # - KMZ_Databas.gdb
output_db = skapa_mapp + os.sep + db_path + os.sep + db_name
feature_lyr_name = "TEMP"
def main():
 f_and_list = find_and_list_layers(input_mxd, vag)
 vag_layer = f_and_list[0]
 mxd_layers = f_and_list[1]
 if vag_layer != "":
 selection_stub(mxd_layers) 
def create_feature_layer(in_path, in_name):
 if arcpy.Exists(in_name):
 arcpy.Delete_management(in_name)
 arcpy.AddMessage("Deleted : " + str(in_name) + " feature layer" )
 try:
 feature_layer_result = arcpy.management.MakeFeatureLayer(in_path, in_name)
 except:
 arcpy.AddMessage("Could not create feature layer")
 return feature_layer_result
def find_and_list_layers(input_map, lyr_name ): # returns a single lyr [0] and a list of layers[1]
 layer_list = []
 for df in arcpy.mapping.ListDataFrames(input_map):
 for lyr in arcpy.mapping.ListLayers(input_map, "", df):
 if lyr.name.lower() != lyr_name.lower():
 # We dont want to find features 70 meters from themselves. Remove them from the list
 layer_list.append(lyr)
 elif lyr.name.lower() == lyr_name.lower():
 matched_layer = lyr
 else:
 arcpy.AddMessage("Could not match a layer with name : " + lyr_name)
 matched_layer = ""
 return_data = [matched_layer, layer_list]
 return return_data
def selection_stub(layers_list):
 for lyr in layers_list:
 if str(lyr.workspacePath).endswith(".gdb"):
 file_path = lyr.workspacePath + os.sep + lyr.datasetName
 else:
 file_path = str(lyr.workspacePath) + os.sep + str(lyr.datasetName) + ".shp"
 print file_path
 output_name = str(lyr.name).lower()[0:7] # you can work your name logic in here. My map is using simple names.
 try:
 feature_lyr = create_feature_layer(file_path, feature_lyr_name)
 except:
 arcpy.AddMessage("could not create feature layer" )
 ##-----feature layer is created process selections.
 try:
 result = arcpy.SelectLayerByLocation_management(feature_lyr, "WITHIN_A_DISTANCE", "", "70 Meters","NEW_SELECTION")
 except:
 arcpy.AddMessage("Could not process selection")
 sf = result.getOutput(0)
 count = arcpy.GetCount_management(sf)
 if count > 0:
 arcpy.AddMessage("Selection Count : " + str(count))
 copy_features_into_db(sf,output_name)
def copy_features_into_db(input_data, db_name):
 print "In copy features : Input data --- " + str(input_data)
 database = output_db + os.sep + db_name + str(randint(100,299)) # replace this with your name logic.
 print str(database)
 print arcpy.GetCount_management(input_data)
 try:
 arcpy.CopyFeatures_management(input_data, database )
 except:
 print arcpy.GetMessages()
 arcpy.AddMessage("Could not copy features. ")
if __name__ == '__main__':
 main()
answered Nov 10, 2012 at 0:14
3
  • Thanks for taking a look at my code! I’ll see what I can do about the names, I am somewhat tied up in the "old ways" of or mapping architecture and naming, but I’ll see what I can do. I’ll take a look at your code and see if that does the trick. Commented Nov 12, 2012 at 5:32
  • I began to edit my code but I first tried to change the output GDB from file to personal. That did the trick, do you know why this change was enough? I mean, what’s so different between a personal and a file GDB Commented Nov 12, 2012 at 8:23
  • Permissions? When in doubt check permissions. Commented Nov 12, 2012 at 18:04

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.