Hi, I'm trying to publish a map service using Python and ArcPy.
Even though I set sddraft.overwriteExistingService = True, the service is always published with a timestamp appended (e.g., Tainan_ZonePrice_202505151610) instead of overwriting the existing service.
I have already registered the target folder on the GIS Server, and the service name I'm using matches the one that already exists in that folder.
Here is a simplified version of my code:
import arcpy
import os
import xml.dom.minidom as DOM
from dataclasses import dataclass
import requests
import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom
# Modify portal URL, username, and password
portal_url = "https://test/portal"
server_username=""
server_password=""
arcpy.SignInToPortal(portal_url , server_username, server_password)
print("Signing in to portal...")
@dataclass
class Service:
aprx_name: str # Project file name
aprx_path: str # Path to the .aprx file
serverFolder: str # Folder on the server to publish to
map: str # Map name (only needed if named)
service_name: str # Name of the service
mapOperations: str # Operations (Map, Data, Query)
maxRecordCount: str # Max record count (default is 2000)
groups: str # Shared groups, separated by commas (e.g., "Group A,Group B")
sharingLevel: str # Sharing level: OWNER, ORGANIZATION, or EVERYONE
MapImage = {
1: Service("Tainan_ZonePrice", r"D:\MapData\Tainan_ZonePrice\Tainan_ZonePrice.aprx", "publish_test", "map", "Tainan_ZonePrice", "Map,Data,Query", 2000, "", "EVERYONE")
}
print(MapImage[1].aprx_name)
for key in [1]:
try:
# Output folders
outdir_1 = r"D:\MapData\sddraft"
outdir_2 = r"D:\MapData\sd"
# Generate filenames for draft and service definition
aprx_name = MapImage[key].aprx_name
sddraft_filename = aprx_name + ".sddraft"
sddraft_output_filename = os.path.join(outdir_1, sddraft_filename)
sd_filename = aprx_name + ".sd"
sd_output_filename = os.path.join(outdir_2, sd_filename)
aprx_path = MapImage[key].aprx_path
aprx = arcpy.mp.ArcGISProject(aprx_path)
print(aprx.listMaps())
m = aprx.listMaps(MapImage[key].map)[0]
print(m)
service_name = MapImage[key].service_name
print(service_name)
# Replace with your federated server URL
federated_server_url = "https://test/server"
server_type = "FEDERATED_SERVER"
sddraft = m.getWebLayerSharingDraft(server_type, "MAP_IMAGE", service_name)
sddraft.federatedServerUrl = federated_server_url
sddraft.enableCache = True
sddraft.cache.configuration = r"D:\MapData\ArcGIS_Online_Bing_Maps_Google_Maps.xml" # Tiling scheme
sddraft.overwriteExistingService = True
sddraft.copyDataToServer = False
sddraft.portalFolder = MapImage[key].serverFolder
sddraft.serverFolder = MapImage[key].serverFolder
sddraft.maxRecordCount = MapImage[key].maxRecordCount
sddraft.mapOperations = MapImage[key].mapOperations
sddraft.sharing.sharingLevel = MapImage[key].sharingLevel
sddraft.sharing.groups = MapImage[key].sharingLevel
sddraft.exportToSDDraft(sddraft_output_filename)
# Modify the XML
doc = DOM.parse(sddraft_output_filename)
# Preserve original XML declaration
original_declaration = None
with open(sddraft_output_filename, 'r', encoding='utf-8') as f:
first_line = f.readline().strip()
if first_line.startswith('<?xml'):
original_declaration = first_line
# Modify configuration properties
try:
config_props = doc.getElementsByTagName('ConfigurationProperties')[0]
properties = config_props.getElementsByTagName('PropertyArray')[0]
prop_sets = properties.getElementsByTagName('PropertySetProperty')
for prop_set in prop_sets:
keys = prop_set.getElementsByTagName('Key')
if keys and keys[0].firstChild:
key_value = keys[0].firstChild.nodeValue
values = prop_set.getElementsByTagName('Value')
if key_value == "minScale" and values and values[0].firstChild:
values[0].firstChild.nodeValue = "295828763.795777"
print("minScale set")
elif key_value == "maxScale" and values and values[0].firstChild:
values[0].firstChild.nodeValue = "70.5310735"
print("maxScale set")
elif key_value == "isCached" and values and values[0].firstChild:
values[0].firstChild.nodeValue = "true"
print("isCached set")
except Exception as e:
print(f"Error modifying configuration properties: {str(e)}")
# Save XML preserving original format
with open(sddraft_output_filename, 'w', encoding='utf-8') as f:
xml_declaration = original_declaration if original_declaration else '<?xml version="1.0" encoding="utf-8"?>'
f.write(xml_declaration + '\n')
f.write(doc.documentElement.toxml())
print("Deleting existing .sd file")
if os.path.exists(sd_output_filename):
os.remove(sd_output_filename)
print("Start staging")
arcpy.server.StageService(sddraft_output_filename, sd_output_filename)
warnings = arcpy.GetMessage(1)
print(warnings)
print("Publishing service...")
print("Start uploading")
federated_server_url1 = "https://test/server/rest/services/publish_test"
results = arcpy.server.UploadServiceDefinition(sd_output_filename, federated_server_url1)
print("Upload complete")
print("Start managing cache tiles")
service_url = f"https://test/server/rest/services/publish_test/{service_name}/MapServer"
scales = "295828763.795777;147914381.897889;73957190.948944;36978595.474472;18489297.737236;9244648.868618;4622324.434309;2311162.217155;1155581.108577;577790.554289;288895.277144;144447.638572;72223.819286;36111.909643;18055.954822;9027.977411;4513.988705;2256.994353;1128.497176"
arcpy.server.ManageMapServerCacheTiles(service_url, scales, "RECREATE_ALL_TILES")
print("Cache management complete")
except arcpy.ExecuteError:
msgs = arcpy.GetMessages(2)
print(f"Arcpy execution error: {msgs}")
except Exception as e:
print(f"Other error occurred: {e}")
No matter what I try, ArcGIS Server always appends a timestamp to the service name instead of overwriting the existing one.
I have confirmed that:
The service name matches an existing service.
The folder is correctly registered.
The overwriteExistingService flag is set to True.
Is there anything I am missing to ensure the existing service is truly overwritten, instead of creating a new one with a timestamp suffix?
Thanks in advance!