I'm using ArcGIS Pro 2.9.5. I'm not a newbie but am having trouble with script tool output. I have a custom tool where I want the output feature classes to be written to a file geodatabase that is specified in a parameter of my script tool. The parameter type is Workspace, Direction is Output, and there is a Filter for Workspace | Local Database. I have the setting "Allow geoprocessing tools to overwrite existing datasets" checked because I need that to overwrite feature classes and text file outputs, if they exist. If I change the direction to Input this works, but I am trying to have the flexibility in my script to use an existing gdb if it exists, and create the gdb if it doesn't already exist. Maybe that is important for understanding my issue.
In my tool dialog if I browse to and select an existing geodatabase, I get the warning 000725 that the dataset already exists. In my mind I think this is ok, because I will be writing feature classes to that gdb. But if I run the tool, the gdb is deleted. I can create it again via arcpy and then it is recognized, but that doesn't work for my use case. I would expect a feature class to be overwritten but not the gdb which holds it. I've had the same problem when I want to write out csvs and other data to a folder that already exists - the whole folder is deleted when I hit run! When I run the same code through the Python window, this behavior doesn't happen - it recognizes that the gdb already exists.
I thought maybe it was arcpy.Exists() screwing up so I added checks using os.path.exists() and same results, so I'm at a loss. Can I not write geoprocessing output to an existing geodatabase specified in a script tool parameter? It seems like I'm missing something fundamental here...
This is my code to try to document what is happening.
import arcpy
import os
def log(message):
arcpy.AddMessage(message)
print(message)
# parameter 0 details:
# Type = Workspace
# Direction = Output
# Filter = Workspace | Local Database
geodatabase = arcpy.GetParameterAsText(0)
log(f"Parameter 0 = {geodatabase}")
gdb_dir = os.path.dirname(geodatabase)
gdb_name = os.path.basename(geodatabase)
gdb_files = [os.path.join(gdb_dir, file) for file in os.listdir(gdb_dir) if file.endswith(".gdb")]
log(r"os.listdir finds the following gdbs:")
log(gdb_files)
if arcpy.Exists(geodatabase):
log("Geodatabase exists (arcpy)")
else:
log("Geodatabase doesn't exist (arcpy)")
if os.path.exists(geodatabase):
log("Geodatabase exists (os.path)")
else:
log("Geodatabase doesn't exist (os.path)")
log("Now I will create the gdb via arcpy")
arcpy.management.CreateFileGDB(gdb_dir, gdb_name)
if arcpy.Exists(geodatabase):
log("Geodatabase exists (arcpy)")
else:
log("Geodatabase doesn't exist (arcpy)")
if os.path.exists(geodatabase):
log("Geodatabase exists (os.path)")
else:
log("Geodatabase doesn't exist (os.path)")
Any advice would be greatly appreciated.
Hi @AD_NLD I believe you want to keep you workspace parameter as an optional Input. If the geodatabase exists, you can select it, if it does not exist the code can create it based on the path entered by the user. Which leads to a question, do you want the user to specify the entire path to the geodatabase if it does not exist? i.e. C:\temp\data\parcels.gdb
Hello @JakeSkinner , thanks for replying. Unfortunately no, setting the parameter as optional didn't work for me. I can create a new gdb if it doesn't exist on the first run. But if I immediately run it again with the same parameter0 value I get the warning that the dataset already exists and when I run the script the gdb is immediately deleted then recreated. I expect my use case to be fairly normal - I create a gdb and write data to it. Then I want to write more data to the existing gdb - but I can't because the gdb is deleted before being freshly created, which wipes out the earlier data.
To answer your question, yes, in this case the user should be able to direct the output to wherever they want in the storage.
I hope this answers...
To overwrite existing feature classes without returning an error you normally need to set the overwriteOutput environment variable to True before attempting to overwrite. Perhaps the "Allow geoprocessing tools to overwrite existing datasets" enables the same functionality? I'm not sure since I haven't used it.
arcpy.env.overwriteOutput = True
Also, it appears you are unconditionally creating the geodatabase. You should put it under the appropriate if-else scope, so it is only created if the geodatabase does not exist. Maybe this is why your geodatabase gets deleted and recreated?
For example:
if arcpy.Exists(geodatabase):
log("Geodatabase exists (arcpy)")
else:
log("Geodatabase doesn't exist (arcpy)")
log("Now I will create the gdb via arcpy")
arcpy.management.CreateFileGDB(gdb_dir, gdb_name)
Hi there @Marshal - the application environment setting I referenced trickles down to the tool, so I don't have to specifically set the overwrite.Output = True as it agrees with my application setting (Geoprocessing environment settings—ArcGIS Pro | Documentation).
Yes, I was unconditionally creating the database at that part of the code just to test if the Exists statements afterwards worked, because I wasn't really trusting of anything at that point. I realize it is confusing, my apologies for that.
Ahh ok, makes sense. It did seem too obvious! Haha
Can you share the original code that is not working as expected?
This is the top part of the script where all this stuff happens.
# imports
import arcpy
import os
# parameters
fc_folders = arcpy.GetParameterAsText(0).split(";")
output_gdb = arcpy.GetParameterAsText(1)
# get output directory and gdb name
output_dir = os.path.dirname(output_gdb)
gdb_name = os.path.basename(output_gdb)
gdb_fc_list_file = os.path.join(output_dir, "gdb_fc_list.txt")
shp_fc_list_file = os.path.join(output_dir, "shp_fc_list.txt")
# check for existence of the gdb
gdb_full_path = os.path.join(output_dir, gdb_name)
if not arcpy.Exists(gdb_full_path):
arcpy.AddMessage(f"'{gdb_full_path}' not found. Creating it...")
arcpy.management.CreateFileGDB(output_dir, gdb_name)
else:
arcpy.AddMessage(f"Using existing gdb '{gdb_full_path}'")
And here are the simple parameters used
After some brief testing, I am getting the same behavior as you describe when the parameter direction is set to Output (i.e. The geodatabase is created/overwritten every time).
The tool functions as expected when the direction is set to Input instead (i.e. The geodatabase is only created if it does not exist).
Are you planning on using this script tool in Model Builder? If not, maybe you can just set the direction to Input?
If you are planning to use with Model Builder or chaining with other tools, maybe you can use SetParameter to add the output geodatabase as an additional parameter set to Output?
https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/setparameterastext.htm