MapDocument.saveACopy() Error

753
1
05-03-2013 07:18 AM
AndrewEgleton
New Contributor III
Hi,

I've getting an error with the saveACopy function of an arcpy MapDocument, it will not let me saveACopy of a document I created using saveACopy then later renamed back to the original documents name.
This is my workflow, looping through a folder full of MXDs:

  1. Open original document

  2. Do some work on it

  3. Save a copy with new name

  4. Close all documents

  5. copy the original document to an archive folder (only copying those documents that had work done to them successfully)

  6. delete the original document (in the original folder)

  7. rename the saved copy to the original documents name (in the original folder)

This works fine the first time it is run on a folder, if it is run a second time on the same folder (which now has some new documents), it will fail to saveACopy for all documents that were modified the first time around.

This sample function illustrates the problem:
import arcpy, os, gc
def Test():
    # Test mode
    justSaveAs = True


    # Test MXD
    originalDoc = r"C:\Users\USERNAME\Documents\ArcGIS\TestData\Test.mxd"


    # Make a new MXD Name...
    baseFldr = os.path.dirname(originalDoc)
    baseName = os.path.basename(originalDoc)
    newDoc = os.path.join(baseFldr,"temp123_" + baseName)


    # Open the original Document, and save a copy
    mxd = arcpy.mapping.MapDocument(originalDoc)
    mxd.saveACopy(newDoc)


    # Close the document
    del mxd
    gc.collect()


    # Delete the original and rename the new file the same as the original
    os.remove(originalDoc)
    os.rename(newDoc,originalDoc)


    if justSaveAs:
        # Reopen the document and try and save as again -- FAILS
        mxd = arcpy.mapping.MapDocument(originalDoc)
        mxd.saveACopy(newDoc)
    else:
        # Reopen the document, save, then save as -- WORKS!?
        mxd = arcpy.mapping.MapDocument(originalDoc)
        mxd.save()
        mxd.saveACopy(newDoc)


It does work ok if you open the new version of a document and do a regular save before atempting to saveACopy. Also works by opening the new version of the document before renaming them and do saveACopy back to the original name.
However both of these solutions require reopening the document which can take some time for large maps, and there is no way to tell before hand if the document will suffer from the saveACopy issue.

This issue only affects arcpy, opening the documents in ArcMap and doing save/save as/save a copy works fine for all MXDs.

Any ideas on how to fix this?
Tags (2)
0 Kudos
1 Reply
MikeHunter
Occasional Contributor
I ran your code, and sure enough, it runs fine the first time but fails after that.  Not only that, but if I try to open the mxd that has gone through the process, I can't save it in Arcmap.  All I can do is a Save a Copy.  At this point the mxd can't quite figure out what its name is and is for all practicable purposes corrupt.  Seems like a bug to me.

That said, the code below will work repeatedly if you can work it into your process.  The issue was the filesystem calls os.rename and os.remove. So we just do it all with arcpy:

   
    originalDoc = r'C:\temp\Untitled.mxd'

    # Make a new MXD Name...
    baseFldr = os.path.dirname(originalDoc)
    baseName = os.path.basename(originalDoc)
    newDoc = os.path.join(baseFldr,"temp123_" + baseName)

    # Open the original Document, and save a copy
    mxd = arcpy.mapping.MapDocument(originalDoc)
    mxd.saveACopy(newDoc)
    
    mxd = arcpy.mapping.MapDocument(newDoc)
    mxd.saveACopy(originalDoc)    
    
    mxd = None


This will be slower than what you were trying to do if the mxd's are large, as you said. The basic issue is the mixing of filesystem calls and saveACopy.  Probably the fastest way to handle your work flow is eliminate the saveACopy calls completely. Something like this:

originalDoc = r'C:\temp\Untitled.mxd'

# Make a new MXD Name...
baseFldr = os.path.dirname(originalDoc)
baseName = os.path.basename(originalDoc)
old_doc = os.path.join(baseFldr,"orig_" + baseName)

# make a copy of the original with a new name
shutil.copy2(originalDoc, old_doc)

# Open the original Document, do the work, and set work_done flag
mxd = arcpy.mapping.MapDocument(originalDoc)

# do some work here if necessary, set flag depending on if
#anything was done or not. We'll set to true for demonstration
work_done = True 

if work_done:
    mxd.save()
    # move the original to an archive folder
    afol = r'C:\temp\Archive'
    dest = os.path.join(afol, baseName)
    shutil.move(old_doc, dest)
else:
    os.remove(old_doc)    

mxd = None




good luck,
Mike
0 Kudos