I am in the process of developing a tool as a Python Toolbox to be published as a Geoprocessing Service using ArcGIS for Server 10.3.
After publishing and running my tool from a sandbox environment I am encountering broken links between the two .lyr files set as the output parameters in and the two Feature Classes that serve as their Data Sources.
Investigation into the issue seems to indicate that the link between .lyr file and Feature Class, made as the final step in the Toolbox using the following method...
g_ESRI_variable_3 = os.path.join(arcpy.env.packageWorkspace,u'tooldata') #one of many variables automatically created after publishing to server (...) toolDataPath = g_ESRI_variable_3 gdbpath = os.path.join(toolDataPath, "data.gdb") # base staging data used every time the rool is executed arcpy.env.scratchWorkspace = '\\\\aus1-gds-darc01/data-store/ToolData/scratch/scratch.gdb' env.workspace = arcpy.env.packageWorkspace scratch = env.scratchGDB scratchfolder = env.scratchFolder (...) # replace datasources of .lyr files to link with respective feature classes lyr1 = arcpy.mapping.Layer(outlayerfileL) lyr1.name = "legend" + nowstring lyr1.replaceDataSource(scratch, 'FILEGDB_WORKSPACE', "legend" + nowstring, True) lyr1.save()
... is not kept once the output data is copied from Server's pre-designated scratch location to the location where outputs from processed jobs are kept.
There are no other errors in running the tool nor does it fail unless the subset of data attempted is too large. The data source link can be repaired manually after running using the typical methods. This problem does not occur when the Python Toolbox is run locally. Is there anything I can do to the code published to server that can fix this? I'm hesitant to attempt to do so.
Thank you in advance for any advice.
Solved! Go to Solution.
Solution seems to be to set up seperate local and server-based versions of arcpy.mapping.Layer.replaceDataSource:
############################################################################################
######### replace datasources of .lyr files to link with respective feature classes - SERVER
serverbase = '\\\\aus1-hen-mmap01v'
scratchcut = scratch[3:]
datalocation = os.path.join(serverbase, scratchcut)
lyr1 = arcpy.mapping.Layer(outlayerfileL)
lyr1.name = "legend" + nowstring
lyr1.replaceDataSource(datalocation, 'FILEGDB_WORKSPACE', "legend" + nowstring, False)
lyr1.save()
lyr2 = arcpy.mapping.Layer(outlayerfileO)
lyr2.name = "output" + nowstring
lyr2.replaceDataSource(datalocation, 'FILEGDB_WORKSPACE', "output" + nowstring, False)
lyr2.save()
##########################################################################################
##########################################################################################
######### replace datasources of .lyr files to link with respective feature classes - LOCAL
# lyr1 = arcpy.mapping.Layer(outlayerfileL)
# lyr1.name = "legend" + nowstring
# lyr1.replaceDataSource(scratch, 'FILEGDB_WORKSPACE', "legend" + nowstring, True)
# lyr1.save()
# lyr2 = arcpy.mapping.Layer(outlayerfileO)
# lyr2.name = "output" + nowstring
# lyr2.replaceDataSource(scratch, 'FILEGDB_WORKSPACE', "output" + nowstring, True)
# lyr2.save()
###########################################################################################
Since the post-publish modification doesn't change any of the code that Server automatically alters during publish, this seems to get the job done without much risk. The 'serverbase' variable just needs to be altered in accordance with whatever server the script is being run on (e.g. normal deployment workflows and moving from a development server to a testing server, etc.).
Solution seems to be to set up seperate local and server-based versions of arcpy.mapping.Layer.replaceDataSource:
############################################################################################
######### replace datasources of .lyr files to link with respective feature classes - SERVER
serverbase = '\\\\aus1-hen-mmap01v'
scratchcut = scratch[3:]
datalocation = os.path.join(serverbase, scratchcut)
lyr1 = arcpy.mapping.Layer(outlayerfileL)
lyr1.name = "legend" + nowstring
lyr1.replaceDataSource(datalocation, 'FILEGDB_WORKSPACE', "legend" + nowstring, False)
lyr1.save()
lyr2 = arcpy.mapping.Layer(outlayerfileO)
lyr2.name = "output" + nowstring
lyr2.replaceDataSource(datalocation, 'FILEGDB_WORKSPACE', "output" + nowstring, False)
lyr2.save()
##########################################################################################
##########################################################################################
######### replace datasources of .lyr files to link with respective feature classes - LOCAL
# lyr1 = arcpy.mapping.Layer(outlayerfileL)
# lyr1.name = "legend" + nowstring
# lyr1.replaceDataSource(scratch, 'FILEGDB_WORKSPACE', "legend" + nowstring, True)
# lyr1.save()
# lyr2 = arcpy.mapping.Layer(outlayerfileO)
# lyr2.name = "output" + nowstring
# lyr2.replaceDataSource(scratch, 'FILEGDB_WORKSPACE', "output" + nowstring, True)
# lyr2.save()
###########################################################################################
Since the post-publish modification doesn't change any of the code that Server automatically alters during publish, this seems to get the job done without much risk. The 'serverbase' variable just needs to be altered in accordance with whatever server the script is being run on (e.g. normal deployment workflows and moving from a development server to a testing server, etc.).