Hi, i got a problem with my python toolbox.
First, i have a toolbar (test_addin) with 3 buttons:
Button1 will activate Button2 and deactivate himself. Same thing for Button2.
"Go" will start a tool in a python toolbox.
This tool have a parameter object with a defaut value set to "1" or "2" depending on which button is activated.
The problem is: when i execute the tool, it work one time, but when i try to activate the other button, and then rerun the tool,
the defaut value for the parameter is not refreshing. I have to refresh the python toolbox manually to make it work.
Is there a way to make this work automatically?
Tank you!
Charles
-------------------------------------------
Toolbar:
import arcpy import pythonaddins class ButtonClass1(object): """Implementation for test_addin.button1 (Button)""" def __init__(self): self.enabled = True self.checked = False def onClick(self): button1.enabled = False button2.enabled = True gobutton.enabled = True class ButtonClass2(object): """Implementation for test_addin.button2 (Button)""" def __init__(self): self.enabled = False self.checked = False def onClick(self): button2.enabled = False button1.enabled = True gobutton.enabled = True class GoClass3(object): """Implementation for test_addin.gobutton (Button)""" def __init__(self): self.enabled = False self.checked = False def onClick(self): tbx = r"V:\mes documents\ArcGIS\AddIns\test\Install\Toolbox.pyt" tool = "Tool" arcpy.RefreshCatalog(tbx) pythonaddins.GPToolDialog(tbx, tool)
python toolbox:
import arcpy import test_addin class Toolbox(object): def __init__(self): """Define the toolbox (the name of the toolbox is the name of the .pyt file).""" self.label = "Toolbox" self.alias = "" # List of tool classes associated with this toolbox self.tools = [Tool] class Tool(object): def __init__(self): """Define the tool (tool name is the name of the class).""" self.label = "Tool" self.description = "" self.canRunInBackground = False def getParameterInfo(self): """Define parameter definitions""" reload(test_addin) # First parameter param0 = arcpy.Parameter( displayName="Active button", name="button", datatype="String", parameterType="Required", direction="Input") if test_addin.button1.enabled == True: param0.value = "1" if test_addin.button2.enabled == True: param0.value = "2" params = [param0] return params def isLicensed(self): """Set whether tool is licensed to execute.""" return True def updateParameters(self, parameters): """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed.""" return def updateMessages(self, parameters): """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation.""" return def execute(self, parameters, messages): """The source code of the tool.""" arcpy.AddWarning(parameters[0].valueAsText) return
Solved! Go to Solution.
I think ArcGIS might only load the toolbox once to improve performance. I workaround this by making a temporary copy of the toolbox every time I want to call it.
import os, sys import glob import shutil import tempfile import threading import time import arcpy, pythonaddins class Button(object): # ... def onClick(self): GPToolDialog('path/to/toolbox.pyt', 'ToolName') def GPToolDialog(toolbox, tool): """ * Workaround for NIM089253 - "TypeError: GPToolDialog() takes at most 1 argument (2 given) http://support.esri.com/en/bugs/nimbus/TklNMDg5MjUz * Workaround for defaults only refreshing on first run - copy the pyt (and xml docs) which forces Arc to reload it every time. """ tmpdir = tempfile.mkdtemp(prefix='toolbox') tmpfile = os.path.join(tmpdir,os.path.basename(toolbox)) docs=glob.glob(toolbox[:-4]+'*.xml') shutil.copy(toolbox,tmpdir) for doc in docs:shutil.copy(doc,tmpdir) try: result=pythonaddins.GPToolDialog(tmpfile,tool) except TypeError: pass finally: #Give ArcMap time to load the toolbox before it gets cleaned up threading.Thread(target=rm, args = (tmpdir,3)).start() return None def rm(d, wait=1): time.sleep(wait) try: shutil.rmtree(d) except: pass
I think ArcGIS might only load the toolbox once to improve performance. I workaround this by making a temporary copy of the toolbox every time I want to call it.
import os, sys import glob import shutil import tempfile import threading import time import arcpy, pythonaddins class Button(object): # ... def onClick(self): GPToolDialog('path/to/toolbox.pyt', 'ToolName') def GPToolDialog(toolbox, tool): """ * Workaround for NIM089253 - "TypeError: GPToolDialog() takes at most 1 argument (2 given) http://support.esri.com/en/bugs/nimbus/TklNMDg5MjUz * Workaround for defaults only refreshing on first run - copy the pyt (and xml docs) which forces Arc to reload it every time. """ tmpdir = tempfile.mkdtemp(prefix='toolbox') tmpfile = os.path.join(tmpdir,os.path.basename(toolbox)) docs=glob.glob(toolbox[:-4]+'*.xml') shutil.copy(toolbox,tmpdir) for doc in docs:shutil.copy(doc,tmpdir) try: result=pythonaddins.GPToolDialog(tmpfile,tool) except TypeError: pass finally: #Give ArcMap time to load the toolbox before it gets cleaned up threading.Thread(target=rm, args = (tmpdir,3)).start() return None def rm(d, wait=1): time.sleep(wait) try: shutil.rmtree(d) except: pass
I was just coming to the same conclusion i.e. that "ArcGIS might only load the toolbox once", and searching for a workaround to how to load my GPToolDialog with default values read from an ASCII file, after calling it from a Python AddIn tool that selects a feature and writes its attributes to that ASCII file, when I found your post.
Your workaround works for me!
If I have the ArcMap Python window open I see some errors (see below) go by but none stop it working. I'm just recording the errors here, and not looking for help with them.
Traceback (most recent call last):
File "C:\Users\Graeme\AppData\Local\ESRI\Desktop10.3\AssemblyCache\{15302DB5-BF1B-4509-B327-85E2E8476653}\WSAAddIn_addin.py", line 82, in onMouseDownMap
GPToolDialog(PythonTBX, "GrossPollutantTrap")
File "C:\Users\Graeme\AppData\Local\ESRI\Desktop10.3\AssemblyCache\{15302DB5-BF1B-4509-B327-85E2E8476653}\WSAAddIn_addin.py", line 35, in GPToolDialog
threading.Thread(target=rm, args = (tmpdir,3)).start()
File "C:\Python27\ArcGIS10.3\Lib\threading.py", line 687, in __init__
self.__daemonic = self._set_daemon()
File "C:\Python27\ArcGIS10.3\Lib\threading.py", line 711, in _set_daemon
return current_thread().daemon
File "C:\Python27\ArcGIS10.3\Lib\threading.py", line 1160, in currentThread
return _active[_get_ident()]
TypeError: GPToolDialog() takes at most 1 argument (2 given)
Hmmm, that's what the "try: except TypeError:" handler is supposed to silence, and it does for me on 10.2.2. I remember from GISSE that you're on 10.3. The bug # I referenced in the code suggests adding `print " "` to the except clause.
I tried using
print ""
in place of
pass
in the except clause but it had no effect.
At the moment this is embedded in an application that works so I'm happy to ignore the error. If I get a chance I'll try and extract a simpler test case and pursue further at another time.
I am using 10.3.1.