looking for advice with lyr.replaceDataSource()

694
4
Jump to solution
03-22-2018 02:21 PM
AnnaBuchheit
New Contributor III

Hi there,

This is an evolving script.  I am essentially teaching myself but it's like stumbling around in the dark.  

I have a butt-load of mxd's whose layers' datasources are being changed, both in location and in feature class name (for the most part). I managed to write a script that would walk through a directory and list each mxd, layer name, layer datasource path and layer feature class name and write it to a csv.  That worked fine.  

Now I'm looking to use an altered form of that list to automate the lyr.replaceDataSource() method.

I have got part of the code working, but when it comes to actually changing the datasource it comes up a dud.  

                             

                                          Maybe it's my logic. Maybe the code is too simplistic.  I dunno.   

Now, I have tested it by hardcoding the paths and values in and it works hunky-dory both with single and double quotes.  (thanks to the advice from some helpful people like yourself!)

When I try to use the lists I don't get very far. Maybe someone out there can see what I am doing wrong or leaving out?  any advice would be great!

Here's what I got:

# This script reads a list in csv format and assigns them to variables to be
# used in the lyr.replaceDataSource method. It will then be used to replace old paths with
# new sources and change each layer's feature class and layer name for each map in the directory.
# **This is just a test code for now**

import csv
import arcpy

#     set up blank lists for data

oldP,newF,newL = [],[],[]

#     read data from file and store in lists

with open(r"C:\hardcode_to_Path\dsListTEST.csv", "rb") as dsList:
     r= csv.reader(dsList,delimiter=",")
     for i,row in enumerate(r):
          if i>0:                  #skip the header
               oldP.append(str(row[0]))
               newF.append(str(row[1]))
               newL.append(str(row[2]))
               
#     replace the existing datasource with the new path, feature class name and layer name.
          
               mxd = arcpy.mapping.MapDocument(r"hardcode_to_testMap.mxd")
               for lyr in arcpy.mapping.ListLayers(mxd):
                    if lyr.supports("DATASOURCE"):
                         if lyr.dataSource == oldP:
                              lyr.replaceDataSource(r"Hardcode_to_new_location","None",newF, True)
                              lyr.name = newL
                              print lyr.dataSource
               mxd.saveACopy(r"hardcode_to_Copy_testMap.mxd")
               del mxd
dsList.close()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The list append works... and so does the mxd.saveACopy.  

BUT the important part in between does not do anything.  DUD. 

0 Kudos
1 Solution

Accepted Solutions
LukeWebb
Occasional Contributor III

Following that, I noticed you are trying to compare a feature datasource to oldP... which is actually a list, so cant really be compared. (You need to compare it to the paths insdie this list, as it will never equal the list)

I wrote a version that should probably work:

import csv
import arcpy


#     set up list for data
dataMappingList = []


#     read data from file and store in lists
with open(r"C:\hardcode_to_Path\dsListTEST.csv", "rb") as dsList:
     r= csv.reader(dsList,delimiter=",")
     for i,row in enumerate(r):
         if i>0:  #skip the header

               #To make mapping the old paths to new paths easier, we store each dataset as a list
               data_list_item = [str(row[0]), str(row[1]), str(row[2])]

               #Then we put them in our master list, which will hold a list, of lists!
               dataMappingList.append(data_list_item)




#     replace the existing datasource with the new path, feature class name and layer name.
mxd = arcpy.mapping.MapDocument(r"hardcode_to_testMap.mxd")
for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DATASOURCE"):


        for data_list_item in dataMappingList:
             if lyr.dataSource == data_list_item[0]:
                  lyr.replaceDataSource(r"Hardcode_to_new_location","None",data_list_item[1], True)
                  lyr.name = data_list_item[2]
                  print lyr.dataSource
mxd.saveACopy(r"hardcode_to_Copy_testMap.mxd")
del mxd


dsList.close()
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

4 Replies
RebeccaStrauch__GISP
MVP Emeritus

Although I'm all for learning as you go, you may want to look at the addin I have that will help.  /blogs/myAlaskaGIS/2015/08/31/python-addin-for-data-inventory-and-broken-link-repair?sr=search&searc...‌  

If it's the same relative change for all sources, there is a way to use this to change just the server or path for all.  If the sources aren't broken now, you can just temporarily change the folder name to break them to get a list, if needed.

If you still want to write something so you can learn, you can just change the .addin to .zip and extrace the .py scripts to see what I have done.  I had a massive amount, with all kinds of different sources (including sde, coverages and shapes) so it it a bit more complex than most need it to be.

0 Kudos
LukeWebb
Occasional Contributor III

Theres an indentation issue causing the script to overwrite the mxd for each line in the CSV. Not sure if copy paste issue or actual problem!

#     set up blank lists for data
oldP,newF,newL = [],[],[]

#     read data from file and store in lists
with open(r"C:\hardcode_to_Path\dsListTEST.csv", "rb") as dsList:
     r= csv.reader(dsList,delimiter=",")
     for i,row in enumerate(r):
          if i>0:                  #skip the header
               oldP.append(str(row[0]))
               newF.append(str(row[1]))
               newL.append(str(row[2]))


# replace the existing datasource with the new path, feature class name and layer name.
mxd = arcpy.mapping.MapDocument(r"hardcode_to_testMap.mxd")
for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DATASOURCE"):
         if lyr.dataSource == oldP:
              lyr.replaceDataSource(r"Hardcode_to_new_location","None",newF, True)
              lyr.name = newL
              print lyr.dataSource
mxd.saveACopy(r"hardcode_to_Copy_testMap.mxd")
del mxd


dsList.close()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
LukeWebb
Occasional Contributor III

Following that, I noticed you are trying to compare a feature datasource to oldP... which is actually a list, so cant really be compared. (You need to compare it to the paths insdie this list, as it will never equal the list)

I wrote a version that should probably work:

import csv
import arcpy


#     set up list for data
dataMappingList = []


#     read data from file and store in lists
with open(r"C:\hardcode_to_Path\dsListTEST.csv", "rb") as dsList:
     r= csv.reader(dsList,delimiter=",")
     for i,row in enumerate(r):
         if i>0:  #skip the header

               #To make mapping the old paths to new paths easier, we store each dataset as a list
               data_list_item = [str(row[0]), str(row[1]), str(row[2])]

               #Then we put them in our master list, which will hold a list, of lists!
               dataMappingList.append(data_list_item)




#     replace the existing datasource with the new path, feature class name and layer name.
mxd = arcpy.mapping.MapDocument(r"hardcode_to_testMap.mxd")
for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DATASOURCE"):


        for data_list_item in dataMappingList:
             if lyr.dataSource == data_list_item[0]:
                  lyr.replaceDataSource(r"Hardcode_to_new_location","None",data_list_item[1], True)
                  lyr.name = data_list_item[2]
                  print lyr.dataSource
mxd.saveACopy(r"hardcode_to_Copy_testMap.mxd")
del mxd


dsList.close()
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
AnnaBuchheit
New Contributor III

Ah!  so there it is!  I wasn't comparing the string inside the list, I was just comparing the list!  My inexperience shows

It worked smoothly!  thank you for the guidance!

0 Kudos