Select to view content in your preferred language

Two issues creating a script tool

6531
25
07-17-2015 07:35 AM
BradJones
Deactivated User

I have this script below.  When the three arguments are set as variables and I run the script in the ArcMap Python window to test it it runs perfectly.  I created a tool for this script.  In the parameters for the tool properties I have the Data Types for the 3 arguments are set as "SQL expressions" and all the data types for the feature layers created are "Feature Layers" with a "Type: Derived" and "Direction: Output".

First problem: when I run the tool with the script as is i get this error 'RuntimeError: LayerObject: Set attribute showLabels does not exist'. I remove the code block that applies the labels then I get this error 'ValueError: Unknown value for Extent argument'. Running the script in the mxd both code blocks work perfectly.

Second Problem: I remove both code blocks from the script and run the tool and nothing happens.  No errors. Just doesn't add layers.

# Import modules
import os, arcpy


# Set arguments
pws = arcpy.GetParameterAsText(0)
ass_pws = arcpy.GetParameterAsText(1)
mtr_recpws = arcpy.GetParameterAsText(2)


# Set variables  
sources = r"V:\Source Water Protection\SWAP Model\SWAP.code_newrasters\GIS\SWAP.gdb\sources" # Will need to change if used outside of SWPP staff because of directory permissions. "Sources"  feature class is in WATER_FACILITY.gdb
assessment = r"V:\Source Water Protection\SWAP Model\SWAP.code_newrasters\GIS\SWAP.gdb\assessment_areas" # Will need to change if used outside of SWPP staff because of directory permissions. "Assessments" feature class not in WATER_FACILITY.gdb..
meter = r"V:\WATER_FACILITY\WATER_FACILITY.gdb\MASTER_METER"
files = ["BACTI", "DBP", "DBP_STAGE2", "OFFICE", "PRV", "PUMP_STATION", "SERVICE_AREA_COMBO", "TANK", "VALVE_MISCELLANEOUS", "WTP"] # list all names used for feature classes ans .lyr files. 
layers = ["Bacti", "DBP", "DBP Stage 2", "Office", "PRV", "Pump Station", "Service Area", "Tank","Valve", "Water Treatment Plant"]
src_layer = "Source"
ass_layer = "Assessment Area"
mtr_layer = "Master Meter"
src_symb = r"V:\Source Water Protection\PWS_ID_Tool\SOURCE.lyr"
ass_symb = r"V:\Source Water Protection\PWS_ID_Tool\ASSESSMENT.lyr"
mtr_symb = r"V:\Source Water Protection\PWS_ID_Tool\MASTER_METER.lyr"
root = r"V:\WATER_FACILITY\WATER_FACILITY.gdb" 
symRoot = r"V:\Source Water Protection\PWS_ID_Tool"


# Create directory paths, make feature layers, and apply symbologies.
for i, file in enumerate(files):
    path = os.path.join(root, files) # Create directory path for featureclasses 
    symPath = os.path.join(symRoot, files + ".lyr") # Create directory path for .lyr files
    arcpy.MakeFeatureLayer_management(paths, layers, pws) # Make all the layers from "files" list
    arcpy.ApplySymbologyFromLayer_management(layers, symPaths) # Apply the symbologies from "symNames" list.
    
arcpy.MakeFeatureLayer_management(assessment, ass_layer, ass_pws)
arcpy.ApplySymbologyFromLayer_management(ass_layer, ass_symb)
arcpy.MakeFeatureLayer_management(meter, mtr_layer, mtr_recpws)
arcpy.ApplySymbologyFromLayer_management(mtr_layer, mtr_symb)
arcpy.MakeFeatureLayer_management(sources, src_layer, pws) # Ordered to have the "Source" layer in the 0 position.
arcpy.ApplySymbologyFromLayer_management(src_layer, src_symb)




# Apply label
mxd = arcpy.mapping.MapDocument("CURRENT") # Reference to current open map document. Could insert path.
layer = arcpy.mapping.ListLayers(mxd, "")[0] # Indexing for first layer in table of contents. "Make feature layers" functions ordered so "Source" is in 0 position.
if layer.supports("LABELCLASSES"):  
     for lblclass in layer.labelClasses:  
         lblclass.showClassLabels = True         
lblclass.expression = '"%s" & [SOURCE_ID] & "%s"' % ("<CLR red='255'><FNT size = '12'>", "</FNT></CLR>") 
layer.showLabels = True  
arcpy.RefreshActiveView()


#Apply extent from "Source" layer
mxd = arcpy.mapping.MapDocument("CURRENT") # Using current map, can also use a path to an mxd here  
df = arcpy.mapping.ListDataFrames(mxd)[0]  
lyr = arcpy.mapping.ListLayers(mxd, "", df)[0]  
ext = lyr.getExtent()  
df.extent = ext 

Message was edited by: Brad Jones

0 Kudos
25 Replies
BradJones
Deactivated User

It goes to turd on line 31

0 Kudos
IanMurray
Honored Contributor

Ah, paths is a string not a list, so paths would give you the first character of the string paths (or the letter V in this case).  Take away the index from paths in that tool and it should work.

0 Kudos
BradJones
Deactivated User

This is the code block that is working for me now. So in line 3 where I create the featurelass paths, I'm not creating a 'list' of paths stored in memory, but a bunch of individual strings that are the paths?  I would think path in line 5 would have to be indexed with layers, and the same for symPath?

# Create directory paths, make feature layers, and apply symbologies. 
for i, file in enumerate(files): 
    path = os.path.join(root, files) # Create directory path for featureclasses 
    symPath = os.path.join(symRoot, files + ".lyr") # Create directory path for .lyr files 
    arcpy.MakeFeatureLayer_management(path, layers, pws) # Make all the layers from "files" list 
    arcpy.ApplySymbologyFromLayer_management(layers, symPath) # Apply the symbologies from "symNames" list.
0 Kudos
IanMurray
Honored Contributor

That would not be the case.

Your path is changing each time your for loop runs, based on which file you are using(a list which is being iterated through with enumerate), whereas layers is a list that is NOT being iterated over. Therefore, to get the proper item out of the layers list, you need an index equal to the iteration ([layers).  path and symPath are strings created each time you go through the for loop based on the file(os.path.join returns a string not a list), so using an index on them would return the string characters of the index.

I think you are being a little thrown off since in line 3 and 4, the second parameter is files, which while works for this, is not very pythonic.  Both could be changed to file, since we are in a for-loop, and using the list we are iterating with an index instead of the item that is returned from the loop with the iterator. 

TBH, I have never used the enumerate function, though it works well for what you are doing.  My python is not the strongest, I mainly use it only for use in arcpy, so perhaps a more "pythonic" person would like to explain this more succinctly (Xander Bakker​, Richard Fairhurst​, Dan Patterson​, Wes Miller​)

0 Kudos
BradJones
Deactivated User

What you said makes sense.  Basically, for each loop it starts at line 3, make creates the fc path. Line 4 creates the .lyr path.  Line 5 makes the feature layer using the path created in line 3, and the indexed fc file, and the indexed 'layers', and so on. But as I just proved to myself, 'files' doesn't have to be indexed.  just call them 'file'.

I think...

0 Kudos
BradJones
Deactivated User

BTW, thanks for your help.  I'm having one of those days.  I swear the code block ran as written in the first post.

0 Kudos
WesMiller
Deactivated User

Brad I tested both the labels portion and the extent portions of your script in arcmap and as a script model both worked without any issues

labels

mxd = arcpy.mapping.MapDocument("CURRENT") # Reference to current open map document. Could insert path.  
layer = arcpy.mapping.ListLayers(mxd, "")[0] # Indexing for first layer in table of contents. "Make feature layers" functions ordered so "Source" is in 0 position.  
if layer.supports("LABELCLASSES"):    
     for lblclass in layer.labelClasses:    
         lblclass.showClassLabels = True           
lblclass.expression = '"%s" & [Type] & "%s"' % ("<CLR red='255'><FNT size = '12'>", "</FNT></CLR>")   
layer.showLabels = True    
arcpy.RefreshActiveView() 

Extent

#Apply extent from "Source" layer  
mxd = arcpy.mapping.MapDocument("CURRENT") # Using current map, can also use a path to an mxd here    
df = arcpy.mapping.ListDataFrames(mxd)[0]    
lyr = arcpy.mapping.ListLayers(mxd, "", df)[0]    
ext = lyr.getExtent()    
df.extent = ext   
arcpy.RefreshActiveView()  
0 Kudos
BradJones
Deactivated User

Hmmmm...

0 Kudos
BradJones
Deactivated User

Back to the original two problems.

0 Kudos
WesMiller
Deactivated User

Brad I tested both individually and they both worked for me. See the above code for how i used them the only changes i made were labels code line 6 i changed the field name to work with the field in my data in the extent i added line 7.

0 Kudos