adding layers in a standalone script

4533
11
Jump to solution
04-15-2013 07:27 PM
JonPedder
Occasional Contributor II
Has anyone successfully accomplished this? Seriously I???m not being sarcastic.

What I presumed to be a very simple task has me flummoxed. Simply adding a featureclass as a layer to an mxd.

All commands work perfectly when run in a geoprocessing python session, yet they fail when running in a standalone script. Is it maybe something in my environment settings? I???ve tried to cover them all here.

# Set enviroment arcpy.env.workspace arcpy.env.scratchGDB arcpy.env.scratchFolder


I???ve tried writing the layers to disk then reading them in, adding with AddLayer and AddtoGroup, insertLAyer etc. I can get a layer to add when pulling from disk yet it won???t display in the TOC (you can see it's there if I iterate the layers). I have RefreshTOC and RefrenceActiveView

Here???s a test script I???ve been playing with.

# Add layers to the map mxd = arcpy.mapping.MapDocument(r"C:\Users\mymap.mxd")  # List data frame and layers frame = arcpy.mapping.ListDataFrames(mxd,'Dataframe')[0] refFeatureLayer = arcpy.mapping.ListLayers(mxd,'*New_Layer*',frame)[0]  # create a new layer from an existing featureclass travel_route_1 = "Travel_Routes" tempLayer = arcpy.MakeFeatureLayer_management(travel_route_1,'my test layer')  # Save layer to disk arcpy.SaveToLayerFile_management (tempLayer, r'C:\Users\test layer.lyr')  # List data frame and layers - just to refresh the list, shouldn't need to do this. frame = arcpy.mapping.ListDataFrames(mxd,'Dataframe')[0] refFeatureLayer = arcpy.mapping.ListLayers(mxd,'*test*',frame)[0]  # Get the layer addLayer = arcpy.mapping.Layer(r'C:\Users\test layer.lyr')  # Add the layer to the dataframe arcpy.mapping.AddLayer(frame, addLayer, "BOTTOM")  # List data frame and layers - just to refresh the list, shouldn't need to do this. frame = arcpy.mapping.ListDataFrames(mxd,'Dataframe')[0] refFeatureLayer = arcpy.mapping.ListLayers(mxd,'*test*',frame)[0]  # Finally move the layer movelayer = arcpy.mapping.ListLayers(mxd,'*my*',frame)[0] arcpy.mapping.MoveLayer(frame,refFeatureLayer,movelayer,"AFTER")  arcpy.RefreshTOC() arcpy.RefreshActiveView()
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JonPedder
Occasional Contributor II
This likely isn't one I'd have figured out myself, thanks VERY much Jeff for helping debug this.


From Jeff Barrette

The result of MakeFeatureLayer is a string object, not a layer object.  AddLayer requires a layer object, resultlayer.getOutput(0) - this returns the layer object.

This is one of the subtle differences between GP/arcpy (released at 9x) and arcpy.mapping (released at 10x).  Many arcpy functions return strings and arcpy functions translate them appropriately.  Arcpy.mapping is more object oriented in design and requires more than just string objects.



Here's the code that worked, note the addition of getOutput(0)

 frame = arcpy.mapping.ListDataFrames(mxd,'Dataframe')[0] tempLayer = arcpy.MakeFeatureLayer_management(dissolved_feature,'{0}\Viewshed_{1}'.format(scratchfdr,timestamp)) arcpy.mapping.AddLayer(frame, tempLayer.getOutput(0), "AUTO_ARRANGE") 

Click here for more information on using getOutput(0)

I hope this helps others with the same issue

Jon

View solution in original post

0 Kudos
11 Replies
JeffBarrette
Esri Regular Contributor
If you are referencing the MXD via path (e.g., r"C:\Temp\mymap.mxd") and then making changes, you must save your changes at the end of the script.  Use mxd.save() or mxd.saveACopy(path).

This script probably works if you replace the MXD path with the keyword "current".  I can see that you have refresh functions at the end.  The refresh functions are needed if using current but don't help if working against an MXD on disk.

Jeff
0 Kudos
JonPedder
Occasional Contributor II
Thanks, I do in fact have 'CURRENT' in my master script, this was just a test script.

My script bombs out now on the move layer function, Assertion error. namely that it can't find the layer in the dataframe.

I'll try saving prior to the move and see if that helps.

just ran a test which included mxd.save() prior to the move and received an error List Index Out Of range, which I assume means ListLayers didn't find the layer in question.
0 Kudos
JonPedder
Occasional Contributor II
Jeff, I did manage to save a layer to disk using the scratch folder as the location, figured I could just load it and be done. Ah, not so fast!

I can also read from disk and using AddLayer it 'appears' to work, meaning I don't get an error. If I list the layers using the following it shows in the layer list.

>>> df = arcpy.mapping.ListDataFrames(mxd, "MapSAR")[0]
>>> for d in df:
...     print d


I can see that the layer was added, but looking at the actual mxd the layer isn't shown there, even after RefreshTOC and RefreshView. I manually saved the mxd (selecting save from the file menu), close and reopen, the layer isn't listed. If I rerun the frame iterator the 'hidden' layer is also gone.

I tried this from a fresh mxd thinking a corruption issue, but same thing.

Running 10.1 SP1

Glad to send you the entire script, db etc. if that would help?

cheers

Jon
0 Kudos
JeffBarrette
Esri Regular Contributor
Can you send me a map package and your script to jbarrette@esri.com.

Jeff
0 Kudos
JonPedder
Occasional Contributor II
This likely isn't one I'd have figured out myself, thanks VERY much Jeff for helping debug this.


From Jeff Barrette

The result of MakeFeatureLayer is a string object, not a layer object.  AddLayer requires a layer object, resultlayer.getOutput(0) - this returns the layer object.

This is one of the subtle differences between GP/arcpy (released at 9x) and arcpy.mapping (released at 10x).  Many arcpy functions return strings and arcpy functions translate them appropriately.  Arcpy.mapping is more object oriented in design and requires more than just string objects.



Here's the code that worked, note the addition of getOutput(0)

 frame = arcpy.mapping.ListDataFrames(mxd,'Dataframe')[0] tempLayer = arcpy.MakeFeatureLayer_management(dissolved_feature,'{0}\Viewshed_{1}'.format(scratchfdr,timestamp)) arcpy.mapping.AddLayer(frame, tempLayer.getOutput(0), "AUTO_ARRANGE") 

Click here for more information on using getOutput(0)

I hope this helps others with the same issue

Jon
0 Kudos
by Anonymous User
Not applicable

I realize this is an old thread, but do either of you have a suggestion or fix for when the above script recommended by Jeff Barrette works at the command line but not when run within a tool? I started a new thread here for reference.

0 Kudos
curtvprice
MVP Esteemed Contributor

Madeleine - are you running the tool in the background? If you are doing things to the map document you need to always check the script property "always run in foreground" or turn background processing off.

0 Kudos
by Anonymous User
Not applicable

Curtis -- yes, I've checked the "Always run in foreground" box within the general properties tab for the tool. I should mention that the tool works when the the shapefile is constructed within the python code (from a numpy array) and then added to the map, but it doesn't work when the shapefile already exists in a folder and is then added to the map (see errors from the tool here).

0 Kudos
JeffBarrette
Esri Regular Contributor

Madeline,

For some reason I can’t respond to the thread.

I don’t get the error when I run the following from a script tool within ArcMap.

import arcpy

precipLayer = arcpy.MakeFeatureLayer_management(r"D:\Active\ArcPY\10x\ScrumWorks\Data\Drive_A\basin_utmcopy.shp")

mxd = arcpy.mapping.MapDocument("CURRENT")

df = arcpy.mapping.ListDataFrames(mxd)[0]

arcpy.mapping.AddLayer(df, precipLayer.getOutput(0), "TOP") #NO ERROR

#arcpy.mapping.AddLayer(df, precipLayer, "TOP") #GOT ERROR BUT EXPECTED

What version of the software are you using?

Have you tried using a layer file that references the shapefile on disk?

Replace:

precipLayer = arcpy.MakeFeatureLayer_management(r"D:\Active\ArcPY\10x\ScrumWorks\Data\Drive_A\basin_utmcopy.shp")

with:

precipLayer = arcpy.mapping.Layer(r"D:\Active\ArcPY\10x\ScrumWorks\Data\Drive_A\basin_utmcopy.shp")

Jeff

0 Kudos