Select to view content in your preferred language

Output gdb is overwritten from script tool parameter

121
7
Wednesday
Labels (3)
AD_NLD
by
Emerging Contributor

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.

 

 

 

0 Kudos
7 Replies
JakeSkinner
Esri Esteemed Contributor

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

0 Kudos
AD_NLD
by
Emerging Contributor

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...

0 Kudos
Marshal
Regular Contributor

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)

 

0 Kudos
AD_NLD
by
Emerging Contributor

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.

0 Kudos
Marshal
Regular Contributor

Ahh ok, makes sense.  It did seem too obvious!  Haha

Can you share the original code that is not working as expected?

0 Kudos
AD_NLD
by
Emerging Contributor

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

Capture.PNG

0 Kudos
Marshal
Regular Contributor

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

 

0 Kudos