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?
2 Answers 2
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"):
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()
-
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.Daniel– Daniel2012年11月12日 05:32:45 +00:00Commented 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 GDBDaniel– Daniel2012年11月12日 08:23:03 +00:00Commented Nov 12, 2012 at 8:23
-
Permissions? When in doubt check permissions.theJones– theJones2012年11月12日 18:04:47 +00:00Commented Nov 12, 2012 at 18:04
Explore related questions
See similar questions with these tags.
"C:\Users\dabr\Desktop\KMZtest\\"
becomesr"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.'r'
to it. Sorry I can't be of more help to you.