Select to view content in your preferred language

project_service_aprx_object.save() Error from Pro 2.8.x to 2.9 upgrade

12226
26
Jump to solution
11-23-2021 02:26 PM
Min-DongChang
Occasional Contributor

I have a code that a developer created that no long works for me.  With a recent upgrade from 2.8.x to 2.9, the script no errors out at a line " project_service_aprx_object.save()".  What I believe the code is trying to do update the source of feature layers in a map ("1_Service_Status_On").  However, when it comes to the  project_service_aprx_object.save() line, it gives me the following error:

Traceback (most recent call last):
File "<string>", line 686, in <module>
File "A:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\_mp.py", line 285, in save
return convertArcObjectToPythonObject(self._arc_object.save(*gp_fixargs((), True)))
OSError: G:\SDE_User_Connections\Projects\UnitedStates\US_Test01\Web_Services\Test01_Project_Services.aprx

I'm running the code in an empty APRX file so I don't even have the Test01_Project_Services.aprx open.  I'm a novice at python so any I can provide more of the code if necessary.

0 Kudos
26 Replies
RahulGupta2
New Contributor

I encountered the same problem. To resolve the issue I used the following code.

#Remove existing layer from original template
Original_Template = r"C:\TempScript\original.aprx"
aprx = arcpy.mp.ArcGISProject(Original_Template)
aprxMap = aprx.listMaps("Map")
for lyr in aprxMap[0].listLayers():
      aprxMap[0].removeLayer(lyr)

#Add new layer to original template
_layer = arcpy.MakeFeatureLayer_management(fc,"LayerName").getOutput(0)
aprxMap[0].addLayer(_layer,"BOTTOM")
aprx.saveACopy(r"C:\TempScript\Temp_Template.aprx")

#Save original template to the temp template as aprx.save() is not working
aprx_tmp = arcpy.mp.ArcGISProject(r"C:\TempScript\Temp_Template.aprx")
aprxMap_tmp = aprx_tmp.listMaps("Map")
m = aprxMap_tmp[0]
sddraft = m.getWebLayerSharingDraft("FEDERATED_SERVER", "MAP_IMAGE", "LayerName")

Regards

Rahul

0 Kudos
VincentLantaca
Occasional Contributor

seems like there are still issues with aprx.save() even in 3.1, I can run a geoprocessing script with modifies then saves an .aprx file once after opening ArcGIS Pro, but the same script a second time will give the OSError until I re-open Pro

ASw93
by
Regular Contributor

Can confirm I am seeing this same error still in 3.1. 

JaredPilbeam2
MVP Alum

Still happening in 3.3.

0 Kudos
TaylorCarnell1
Occasional Contributor

This happens when rerunning a script because you are getting a new reference to the project and subsequent references are read only. 
It isn't desirable, but is technically documented behaviour. As per ArcGISProject:

Projects can be referenced multiple times, but only the first reference can be saved directly because the other references will be opened as read-only.

You can solve this using:

try:
    project
except NameError:
    project = arcpy.mp.ArcGISProject(project_path)

If you already have multiple references, your memory will need to be cleared first (kernel or machine restart), before this will help.

It's still possible to get orphaned references in certain conditions, so this isn't bullet proof.

 

GISDepartmentMFM
Occasional Contributor

thank you for leading me in the right direction for a proper solution to this problem

0 Kudos
GISDepartmentMFM
Occasional Contributor

Stable solution found that doesn't require copying the project, do not create any aprx project variables other than the one in the context class:

try:
gis_context.aprx.save()
except:
try:
gis_context.refresh()
gis_context.aprx.save()
except:
ArcGISUtils.log(f"SAVEING ERROR ocured at {function name}")
messagebox.showerror("Error", f"An error occurred in {function name} Please restart the program to run this function")
gis_context.refresh()

Relevant context code:

class ArcGISContext:
"""
Context manager for handling ArcGIS project resources and cleanup.
Ensures proper initialization and cleanup of ArcGIS resources.
"""
def __init__(self):
"""
Initialize the ArcGIS context manager.
Sets up the initial state with no project or geodatabase references.
"""
self.aprx_path = None
self.aprx = None
self.default_gdb = None
self.map = None
self.layer_list = []
self.is_current = None
ArcGISUtils.log("ArcGIS context manager initialized")

def __enter__(self):
"""
Set up ArcGIS project context and resources.
Returns:
ArcGISContext: The initialized context manager
Raises:
Exception: If there is an error initializing the ArcGIS context
"""
try:
def find_most_recent_aprx():
user_folder = os.path.expanduser("~")
arcgis_projects_folder = os.path.join(user_folder, "Documents", "ArcGIS", "Projects")

# Find all .aprx files
aprx_files = []
for root, dirs, files in os.walk(arcgis_projects_folder):
for file in files:
if file.endswith(".aprx"):
full_path = os.path.join(root, file)
aprx_files.append((full_path, os.path.getmtime(full_path)))

# Sort by last modified time
if aprx_files:
return sorted(aprx_files, key=lambda x: x[1], reverse=True)[0][0]
return None
try:
self.aprx_path = "CURRENT"
self.aprx = arcpy.mp.ArcGISProject("CURRENT")
self.is_current = True
except OSError:
recent_project = find_most_recent_aprx()
self.aprx_path = recent_project
self.aprx = arcpy.mp.ArcGISProject(recent_project)
self.is_current = False
self.default_gdb = self.aprx.defaultGeodatabase
try:
self.map = self.aprx.activeMap
lyr_list = self.map.listLayers()
tbl_list = self.map.listTables()
self.layer_list = lyr_list + tbl_list
except AttributeError:
self.map = self.aprx.listMaps()[0]
lyr_list = self.map.listLayers()
tbl_list = self.map.listTables()
self.layer_list = lyr_list + tbl_list

return self
except Exception as e:
ArcGISUtils.log(f"Error initializing ArcGIS context: {str(e)}")
ArcGISUtils.log(traceback.format_exc())
raise
def refresh(self):
"""Refreshes the current context to see changes"""
# Clean up existing resources first
self.__exit__(None, None, None)
# Then reinitialize
return self.__enter__()


def __exit__(self, exc_type, exc_val, exc_tb):
"""
Clean up ArcGIS resources.
Args:
exc_type: Exception type if an exception was raised
exc_val: Exception value if an exception was raised
exc_tb: Exception traceback if an exception was raised
"""
try:
if self.aprx:
del self.aprx
self.aprx_path = None
self.aprx = None
self.default_gdb = None
self.map = None
self.layer_list = []
self.is_current = None
ArcGISUtils.log("ArcGIS context cleaned up successfully")
arcpy.management.ClearWorkspaceCache()

# Force garbage collection
gc.collect()
except Exception as e:
ArcGISUtils.log(f"Error cleaning up ArcGIS context: {str(e)}")
ArcGISUtils.log(traceback.format_exc())


initialize as so in execute:

global gis_context

with ArcGISContext() as gis_context:

 

0 Kudos