Custom Script Tool Crashing

4281
6
12-30-2014 03:26 AM
RyanFortier
New Contributor III

Hello,

I currently have a python script which will replace the data sources on a MXD with broken links. The code seems to work fine as I have run the code a handful of times using relative paths to indicate the location of the MXD and the location of the GDB. My problem begins when I change to relative paths to "GetParameterAsText". Once I do that and turn it into a script tool, it crashes. Any assistance would be appreciated.

Here is the code that works, its a bit messy, but it works.

    import os
    import logging
    logging.basicConfig(level=logging.DEBUG)

    logging.debug("importing arcpy")
    import arcpy
    logging.debug("arcpy loaded")

    arcpy.env.workspace = "Z:\Work\rd\Fortier\World_Index_Test.gdb"

    #Add layer to exisiting MXD with a dataframe named Layer.
    logging.debug("opening map document")
    mxd = arcpy.mapping.MapDocument (r"Z:\Work\rd\Fortier\WorldIndex\World_Index\Templates\World_Index_Template2.mxd")
    logging.debug("map document open")
    logging.debug("accessing data frame")
    df = arcpy.mapping.ListDataFrames (mxd) [0]
    logging.debug("Found dataframe: {}".format(df.name))

    #Check to see if layers exist within GDB and change data source.

    for lyr in arcpy.mapping.ListLayers(mxd, "", df):
    if lyr.isFeatureLayer:
        name = lyr.datasetName
        path = r"Z:\Work\rd\Fortier\World_Index_Test.gdb"
        if  arcpy.Exists(os.path.join(path, name)):
            lyr.replaceDataSource(path, "FILEGDB_WORKSPACE", name)
            logging.info("replaced data source on {}".format(lyr.name))
        else:
            print "skipped because no source"

    else:
        #arcpy.mapping.RemoveLayer(df, lyr)
        print "skipped group"

    #Saves copy of new MXD and deletes original mxd
    logging.debug("Saving new mxd")
    mxd.saveACopy(r"Z:\Work\rd\Fortier\WorldIndex\World_Index\Outputs\Test1.mxd")
    del mxd #addLayer

Now when I attempt to change it on to a script tool it crashes:

    import os
    import logging
    logging.basicConfig(level=logging.DEBUG)

    logging.debug("importing arcpy")
    import arcpy
    logging.debug("arcpy loaded")

    #arcpy.env.workspace = "Z:\Work\rd\Fortier\World_Index_Test.gdb"

    #Add layer to exisiting MXD with a dataframe named Layer.
    logging.debug("opening map document")
    mxd = arcpy.GetParameterAsText(0)
    logging.debug("map document open")
    logging.debug("accessing data frame")
    df = arcpy.mapping.ListDataFrames (mxd)
    logging.debug("Found dataframe: {}".format(df.name))

    #Check to see if layers exist within GDB and change data source.

    for lyr in arcpy.mapping.ListLayers(mxd, "", df):
    if lyr.isFeatureLayer:
        name = lyr.datasetName
        path = arcpy.GetParameterAsText(1)
        if  arcpy.Exists(os.path.join(path, name)):
            lyr.replaceDataSource(path, "FILEGDB_WORKSPACE", name)
            logging.info("replaced data source on {}".format(lyr.name))
        else:
            print "skipped because no source"

    else:
        #arcpy.mapping.RemoveLayer(df, lyr)
        print "skipped group"

    #Saves copy of new MXD and deletes original mxd
    logging.debug("Saving new mxd")
    mxd.saveACopy = arcpy.GetParameterAsText(2)
    del mxd #addLayer

Here is the error I am getting:

Start Time: Tue Dec 30 05:55:36 2014
Running script CreateMXD...
Failed script CreateMXD...

Traceback (most recent call last):
  File "D:\World_Index\WorldIndex\World_Index\Scripts\CreateMXD.py", line 29, in <module>
    df = arcpy.mapping.ListDataFrames (mxd)
  File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\utils.py", line 181, in fn_
    return fn(*args, **kw)
  File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\mapping.py", line 1479, in ListDataFrames
    result = mixins.MapDocumentMixin(map_document).listDataFrames(wildcard)
  File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\arcobjects\mixins.py", line 728, in listDataFrames
    return list(reversed(list(self.dataFrames)))
  File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\arcobjects\mixins.py", line 695, in dataFrames
    return map(convertArcObjectToPythonObject, self.pageLayout.dataFrames)
  File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\arcobjects\mixins.py", line 679, in pageLayout
    return convertArcObjectToPythonObject(self._mxd._arc_object.pageLayout)
AttributeError: 'unicode' object has no attribute '_arc_object'

Failed to execute (CreateMXD).
Failed at Tue Dec 30 05:55:37 2014 (Elapsed Time: 1.41 seconds)

Tags (1)
0 Kudos
6 Replies
AndyOmmen
Occasional Contributor

Hi Ryan,

On your copied code that is failing, it looks like you left off the data frame index value [0] at the end of df = arcpy.mapping.ListDataFrames(mxd). The returned error flags that line of code and basically states it can't get a data frame object. Also, I noticed you commented out the arcpy.env.workspace and did not replace it w/ an input parameter, I wasn't sure if this was intentional but you may want to add another GetParameterAsText line to allow the user to define their workspace environment. I hope this helps.

Andy

0 Kudos
RyanFortier
New Contributor III

Thanks for the reply Andy,

I realized afterwards that I had left out the data frame index value afterwards. The reason why it is missing is because I removed it from the script because I was playing around. The error came with/without the data frame index value.

Also, do you think the workspace matters? I can try running it with a defined workspace, or vice versa. I thought it really wouldn't about defining a workspace, since I am asking for the GDB as a parameter.

0 Kudos
XanderBakker
Esri Esteemed Contributor

One of the errors is at saving the output mxd. Change it to:

mxd.saveACopy(arcpy.GetParameterAsText(2))

Did you test with specifying the exact same parameters as hard coded in your first example script?

I also noticed the error: AttributeError: 'unicode' object has no attribute '_arc_object'

Are you using any non-ASCII characters in the MXD, paths, etc?

0 Kudos
RyanFortier
New Contributor III

Hello Xander, Andy,

Thank you both for the replies. I seemed to have possibly corrected the first problem I had by chaning the script slightly to this:

mxd = arcpy.mapping.MapDocument (arcpy.GetParameterAsText(0))

and:

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

The script tool ran without crashing. However, I have a new issue.

#Saves copy of new MXD and deletes original mxd
logging
.debug("Saving new mxd")
mxd
.saveACopy = arcpy.GetParameterAsText(2)
del mxd #addLayer

I have this portion of my code set as an output parameter within my script tool. I then select the location where the MXD will be saved, and give it a name, click OK, run the tool. The tool runs, however, the new MXD is nowhere to be found. Any ideas/thoughts?

Thanks

0 Kudos
AndyOmmen
Occasional Contributor

Hi Ryan,

For the mxd.saveACopy method, try passing in parameters that build the output file path and don't forget to append ".mxd" at the end of the path string. See the example below:

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
for df in arcpy.mapping.ListDataFrames(mxd😞
    mxd.activeView = df.name
    mxd.title = df.name
    mxd.saveACopy(r"C:\Project\Output\\" + df.name + ".mxd")
del mxd

In your case, if the third user input parameter is a file path string you could use something like: mxd.saveACopy(arcpy.GetParameterAsText(2) + ".mxd").

0 Kudos
AndyOmmen
Occasional Contributor

Hi Ryan,

The environment workspace probably doesn't matter since you are working with MXD layers, I was just trying to replicate the same parameters as you hard coded in the functional script. I think Xander might be on to something w/ the non-ASCII characters. Also, I would try defining the path input parameter outside of your for loop and pass it into the os.path.join method like you currently have it. Good luck!

Andy

0 Kudos