Need Help Changing Paths to SDE

1626
10
04-08-2011 08:45 AM
JeffPickles
Deactivated User
This script works great when dealing with SHPs and GDBs, but crashes Python when I try to run it for SDE data. What am I doing incorrectly?

import arcpy, os
## Input folder containing MXDs you want to change here.
## This should be the root folder.
start = "X:\ArcGIS"

## The os.walk command tells the script to go through
## all subdirectories in the 'start' folder.
for root, dirs, files in os.walk(start):
    for file in files:
        ## This command looks for MXD files and ignores all others.
        if file.endswith(".mxd"):            
            path = os.path.abspath(os.path.join(root, file))
            mxd = arcpy.mapping.MapDocument(path)
            ## The string you want to find, the new string you want to replace it with.
            mxd.findAndReplaceWorkspacePaths(r"X:\ArcGIS\OLD.gdb\Old_Units", r"Database Connections\server.sde\SDE.DBO.New_Units")
            mxd.save()
del mxd


Everything works fine until I put the SDE connection in.
Tags (2)
0 Kudos
10 Replies
FrankVignati
Frequent Contributor
change this:
mxd.findAndReplaceWorkspacePaths(r"X:\ArcGIS\OLD.gdb\Old_Units", r"Database Connections\server.sde\SDE.DBO.New_Units")
to this:
mxd.findAndReplaceWorkspacePaths(r"X:\ArcGIS\OLD.gdb\Old_Units", r"Database Connections\server.sde", False)
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Try using the replaceWorkspaces function:

import os, arcpy

folder = r"C:\TEMP"

for (path, dirs, files) in os.walk(folder):
    for file in files:
        if file.endswith(".mxd"):
                mxd_path = os.path.join(path, file)
                mapdoc = arcpy.mapping.MapDocument(mxd_path)
                mapdoc.replaceWorkspaces(r"C:\DATA\Philadelphia.gdb", "FILEGDB_WORKSPACE",
                                         r"Database Connections\SQL - VECTOR@VECTOR.sde", "SDE_WORKSPACE")
                mapdoc.save()
del mxd_path
del mapdoc
                
0 Kudos
JeffPickles
Deactivated User
Jake,

Will this work even though I have a new feature name?

EDIT: Tried this both with feature names and without. Unknown error on each.

Traceback (most recent call last):
  File "X:\Python_Code\SubDir_Search_and_Replace_w_SDE.py", line 11, in <module>
    r"Database Connections\server.sde\SDE.DBO.New_Units", "SDE_WORKSPACE")
  File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\utils.py", line 181, in fn_
    return fn(*args, **kw)
  File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\_mapping.py", line 754, in replaceWorkspaces
    return convertArcObjectToPythonObject(self._arc_object.replaceWorkspaces(*gp_fixargs((old_workspace_path, old_workspace_type, new_workspace_path, new_workspace_type, validate), True)))
ValueError: MapDocObject: Unexpected error
0 Kudos
JakeSkinner
Esri Esteemed Contributor
I think there may be a bug with the mapping.findAndReplaceWorkspacePaths function.  I've been running some tests with ArcGIS 10 SP1 and cannot seem to get this to work.  For example, I tried a simple test and the paths would not update:

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Temp\Fires.mxd")
mxd.findAndReplaceWorkspacePaths(r"C:\TEMP\test.gdb", r"C:\Temp\Python_Test.gdb")
mxd.saveACopy(r"C:\Temp\Project2.mxd")
del mxd


I would recommend escalating this matter to tech support.
0 Kudos
MathewCoyle
Honored Contributor
This works for me, ArcGIS 10 SP1

import arcpy

arcpy.OverWriteOutput = 1
mxd_path = "C:\\GIS\\IHTP\\testing.mxd"
old_db = "C:\\GIS\\Working\\Python\\Test\\IHTP_FGDB.gdb"
new_db = "C:\\GIS\\ihtp\\IHTP_FGDB.gdb"

mxd = arcpy.mapping.MapDocument(mxd_path)

mxd.findAndReplaceWorkspacePaths(old_db, new_db, True)
mxd.saveACopy("C:\\GIS\\IHTP\\testingTrue.mxd")
del mxd


In regards to the SDE connection, this should work if you are renaming one layer, if there are multiple layers to rename then that would complicate things.

import arcpy
print "Starting"
arcpy.OverWriteOutput = 1
mxd_path = "C:\\GIS\\IHTP\\testing.mxd"
old_db = "C:\\GIS\\Working\\Python\\Test\\IHTP_FGDB.gdb"
old_lyr = "C:\\GIS\\Working\\Python\\Test\\IHTP_FGDB.gdb\\ihtp"
new_lyr = "IHTP_OLD_AUG09"
new_db = ("C:\Users\\coylema\\AppData\\Roaming\\ESRI\\Desktop10.0\\ArcCatalog\\Connection to winms-wooddb.sde")
#new_db = "C:\\GIS\\ihtp\\IHTP_FGDB.gdb"

mxd = arcpy.mapping.MapDocument(mxd_path)
lyrs = arcpy.mapping.ListLayers(mxd)

for i in lyrs:
    if i.supports("DATASOURCE") and i.supports("DATASETNAME") and i.dataSource == old_lyr:
        i.replaceDataSource(new_db, "SDE_WORKSPACE", new_lyr, False)

mxd.saveACopy("C:\\GIS\\IHTP\\testingSDE.mxd")
del mxd
del lyrs
print "Done"


Edit: When changing data sources, I use the SDE file on disk, not the instance from ArcGIS. This is because if another user added the layer to the mxd, or you added it with a previous version of ArcGIS, I have found these links are not always updated in the background dataSource property, even though they connect fine in ArcGIS. Not sure why this is, or if it is just me.
0 Kudos
JeffPickles
Deactivated User
Success! Thanks, Mathew.

I ended up plugging your code into the os.walk command from my previously failed code so it would go through recursive directories. The only issue now is I need to find out how to put a progress bar into the code so I don't just stare at "Starting..." for the length of the process. 😉

Final code:
import arcpy, os

print "Starting"
arcpy.OverWriteOutput = 1
start = r"X:\ArcGIS"
old_db = r"X:\ArcGIS\Old\Old_GDB.gdb"
old_lyr = r"X:\ArcGIS\Old\Old_GDB.gdb\Old_Units"
new_lyr = "SDE.DBO.New_Units"
new_db = ("Database Connections\server.sde")

for root, dirs, files in os.walk(start):
    for file in files:
        if file.endswith(".mxd"):            
            path = os.path.abspath(os.path.join(root, file))
            mxd = arcpy.mapping.MapDocument(path)
            lyrs = arcpy.mapping.ListLayers(mxd)
            for i in lyrs:
                if i.supports("DATASOURCE") and i.supports("DATASETNAME") and i.dataSource == old_lyr:
                    i.replaceDataSource(new_db, "SDE_WORKSPACE", new_lyr, False)
            mxd.save()

del mxd
del lyrs
print "Done"
0 Kudos
MathewCoyle
Honored Contributor
In terms of tracking your script, I like putting print functions in loops (as long as they aren't too large) to tell me what it is doing.

Something simple under your if statement, such as
if file.endswith(".mxd"):
    print file
...


If you want to get real creative, you can get a count of all your mxds first with a similar loop. Keep a count of the number of mxds converted after the datasource as been successfully changed, divide that value by the total count of mxds, round it to the nearest integer, and print every X value, eg 10 percent, 20 percent etc

There is probably an easier way to do that, I've never had occasion to do something of that sort.
0 Kudos
TerrySilveus
Frequent Contributor
Success! Thanks, Mathew.

I ended up plugging your code into the os.walk command from my previously failed code so it would go through recursive directories. The only issue now is I need to find out how to put a progress bar into the code so I don't just stare at "Starting..." for the length of the process. 😉

Final code:
import arcpy, os

print "Starting"
arcpy.OverWriteOutput = 1
start = r"X:\ArcGIS"
old_db = r"X:\ArcGIS\Old\Old_GDB.gdb"
old_lyr = r"X:\ArcGIS\Old\Old_GDB.gdb\Old_Units"
new_lyr = "SDE.DBO.New_Units"
new_db = ("Database Connections\server.sde")

for root, dirs, files in os.walk(start):
    for file in files:
        if file.endswith(".mxd"):            
            path = os.path.abspath(os.path.join(root, file))
            mxd = arcpy.mapping.MapDocument(path)
            lyrs = arcpy.mapping.ListLayers(mxd)
            for i in lyrs:
                if i.supports("DATASOURCE") and i.supports("DATASETNAME") and i.dataSource == old_lyr:
                    i.replaceDataSource(new_db, "SDE_WORKSPACE", new_lyr, False)
            mxd.save()

del mxd
del lyrs
print "Done"


google -> progress bar python you'll get a lot of hits
0 Kudos
JeffPickles
Deactivated User
Yeah, I just went with a quick and dirty
print path

after the save step. Works wells enough for me.
0 Kudos