Select to view content in your preferred language

arcpy make Parameter to be both input/output

4541
4
03-11-2015 04:50 PM
yosukekimura
Occasional Contributor

Hello,

Is it possible to have a arcpy's Parameter which act as both input and output?  Specifically,

  • The parameter is for a file (CSV file)
  • If specified file does not exist, create one and use it as output (this is how my script is written)
  • If specified file exists, read it, do some consistency check with other inputs, and then append to the file
  • If specified file exists but doenst make sense, just delete and start over

I thought about different way to make this happen, but issues I have are

  1. if parameter is output, then the file got deleted before execute() method got called.  so I cannot use output
  2. if I make parameter to input, the toolbox's dialog doesn't let me specified non-existent name, forces me to pick existing file name.  that's not what I want, because the file is actually output
  3. so I may set parameter as output, and do the testing in updateMessage() method, and if I want to append, I copy the parameter value to a hidden input parameter and then delete value from the output parameter?  is this feasible?
  4. I can have two boxes, one for input, other for output, and pick the one that make sense.  but. the UI is going to be very confusing.
  5. one other way is to not set this parameter to string was something.  but then the file browser like behavior of the UI doesn't work (is there way to use the browser like interface for any variable?

If there is some simple method to do this, please let me know.

0 Kudos
4 Replies
benberman
Regular Contributor

can you post your script for us to review?

0 Kudos
yosukekimura
Occasional Contributor

I have the Tool as class, but it's rather large.  I can make stripped down version if needed.  But really, I haven't done much beyond very basic things.  I just asked before spending hours for reinventing wheels

This is what I have for the parameter right now

def getParameterInfo(self):
    # other params ...

    ## Output parameter

    out_csv = arcpy.Parameter(
            displayName="Output CSV File (.csv)",
            name="out_csv",
            datatype="DEFile",
            parameterType="Required",
            direction="Output")
    out_csv.filter.list = ['csv']
    # more...

In the updateMessage(), I have this piece of code, where I may write checking code instead of write(f.next()) .

def updateMessage(self, parameters):
    # other things...

    # my test
    canappend = False
    pth = out_csv.valueAsText
    if pth is not None and os.path.exists(pth):
        # so this does lets me read the file
        # so suppose i write some small code to do the check, and call that when needed
        with open(pth,'r') as f:
            # TODO this part should be some testing code
            fo.write(f.next())
            canappend = True
    # more tests ...
0 Kudos
yosukekimura
Occasional Contributor

Here is more or less what I would do...  I am taking method 4 of my original post.

Tool has two boxes, one grayed out (Figure 1).  Usually specify output file name in top box (Figure 2).  If I put a file which has partial but valid data, script moves the file name to bottom clear the top box (Figure 3).  execute() find value for the second box (Parameter in_csv ) instead of the first box (out_csv), and append the data.  If the file provided is not compatible with the tool, tool is going to overwrite the file (Figure 4).  Code at the end.

Figure 1. Intial dialog

append.png

Figure 2. New file

append_new.png

Figure 3. Appending to partial file. I set the file name in first box, and the script judge that it is for appending and move it the second box

append_append.png

Figure 4. Overwriting existing file.  In this case the csv file I provided is not what's expected for appending, so tool is going to overwrite.

append_overwrite.png

The code:

(too long?)

williamwinner
Occasional Contributor

That's a bit of an inspired solution.  It's silly that ESRI doesn't allow you to append to an output and you can't select an input that doesn't exist.  But doing this allows it to work well.  I just wanted to add to this with some code.  Here's how I implemented that Validation code:

def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    self.params = arcpy.GetParameterInfo()
    self.params[2].enabled = False

def updateParameters(self):
    """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed."""
    if self.params[1].altered:
        if not self.params[1].value is None:
            if arcpy.Exists(self.params[1].value):
                self.params[2].value = self.params[1].valueAsText
                self.params[1].value = None
            else:
                self.params[2].value = None
    return

def updateMessages(self):
    """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation."""
    if self.params[1].value is None and self.params[2].value is None:
        self.params[1].setErrorMessage("Must enter a value")
    else:
        self.params[1].clearMessage()
    return

params[1] is an output featureclass.  params[2] is an input featureclass.  Both are optional.

0 Kudos