POST
|
I've attached a simple example (counts the number of times UpdateParameters is called) of how I share data between tools in a python toolbox. My guess is that it is similar to what you are already doing - using globals. There probably is a more elegant way but I've run into the same problems that you describe and finally settled on this because it does work. # -*- coding: utf-8 -*-
import arcpy
tool_1_data = dict()
tool_2_data = dict()
class Toolbox(object):
def __init__(self):
self.label = "Toolbox"
self.alias = "toolbox"
self.tools = [Tool_1, Tool_2]
def get_tool_data (tool_data_dict, tool_data_key):
if tool_data_key in tool_data_dict.keys():
return tool_data_dict[tool_data_key]
else:
return None
class Tool_1(object):
def __init__(self):
self.label = "Tool_1"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
global tool_1_data
if len(tool_1_data) == 0:
tool_1_data = {'my_count': 0}
my_count = arcpy.Parameter(displayName="My Count", name="my_count", datatype="GPLong", parameterType="Optional", direction="Input")
other_count = arcpy.Parameter(displayName="Other Count", name="other_count", datatype="GPLong", parameterType="Optional", direction="Input")
return [my_count, other_count]
def updateParameters(self, parameters):
global tool_1_data
global tool_2_data
tool_1_data['my_count'] += 1
parameters[0].value = get_tool_data(tool_1_data, 'my_count')
parameters[1].value = get_tool_data(tool_2_data, 'my_count')
return
def execute(self, parameters, messages):
return
class Tool_2(object):
def __init__(self):
self.label = "Tool_2"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
global tool_2_data
if len(tool_2_data) == 0:
tool_2_data = {'my_count': 0}
my_count = arcpy.Parameter(displayName="My Count", name="my_count", datatype="GPLong", parameterType="Optional", direction="Input")
other_count = arcpy.Parameter(displayName="Other Count", name="other_count", datatype="GPLong", parameterType="Optional", direction="Input")
return [my_count, other_count]
def updateParameters(self, parameters):
global tool_1_data
global tool_2_data
tool_2_data['my_count'] += 1
parameters[0].value = get_tool_data(tool_2_data, 'my_count')
parameters[1].value = get_tool_data(tool_1_data, 'my_count')
return
def execute(self, parameters, messages):
return
... View more
12-11-2023
03:20 PM
|
1
|
1
|
338
|
POST
|
My guess is that arcpy python code is just a thin layer around compiled C code which does all the heavy lifting, so trying to optimize that thin layer would not buy you very much. Using techniques such as in-memory feature classes, caching objects in python dicts and even multithreading can provide really significant performance improvements
... View more
11-17-2023
06:52 AM
|
2
|
4
|
463
|
POST
|
Does this help? https://community.esri.com/t5/python-questions/update-definition-on-layer-in-feature-service/td-p/1067731
... View more
11-11-2023
06:24 AM
|
0
|
0
|
155
|
POST
|
Do you mean "last modified" for the ArcGIS Item or for the associated data? I have some code that tries to find the last time the data was changed. It only works for hosted feature layers. It does not work on feature layers proxied to an ArcGIS server REST service. For those I resort to detecting when the record count changes - not perfect but good enough. Of course if edit tracking is turned on then that makes it easy but I don't own the feature layers so I can't do that. datetime.datetime.fromtimestamp(int(arcgis.features.FeatureLayer(<feature_layer_url>).properties['editingInfo']['dataLastEditDate'])/1000)
... View more
10-30-2023
07:27 AM
|
0
|
2
|
346
|
POST
|
Would something like this work? p1.filter.list = [f.name for f in arcpy.ListFields(p0.value) if f.name not in ['OBJECTID', '<other undesireable fields>']]
... View more
10-12-2023
07:38 AM
|
1
|
1
|
391
|
POST
|
We switched to a "Single Use License" for the user that runs the script in order to eliminate the licensing timeouts. I'm not sure if this is best practices but we also store all of the required credentials in the Windows keystore instead of hardcoding them in the script
... View more
10-01-2023
04:02 PM
|
1
|
0
|
691
|
POST
|
That did the trick - exactly what I was looking for. The append that previously ran almost three minutes now takes about 1 second. The script ran as-is (except for editing in my workspace path). It did take an exception for one feature class when removing the metadata but that feature class was of no importance so I just put a handler around it to keep the script running try:
tgt_item_md.save()
except Exception as ex:
print (str(ex)) Thanks @JakeSkinner !
... View more
09-21-2023
09:53 AM
|
0
|
0
|
408
|
POST
|
I have a script that runs every 10 minutes and appends on the average handful of records to an SDE point feature class each time. I noticed that is has been taking almost 3 minutes to do the append which seems unreasonable for 4 or 5 records. I converted the Append to InsertCursor and it how takes about 1 second. But the Append is much simpler and I'd like to get to the bottom of the problem. I've tried suggestions from other posts to no avail: Rebuild the spatial index arcpy.SetLogHistory(False) arcpy.SetLogMetadata(False) I checked the "Documentation" field in the GDB_Items table and see the the xml contents is 82Meg so maybe that really is the problem - where it has to get read in and updated on every Append (even when I thought I turned of metadata and history logging). Does anybody know the best way to clear out the "Documentation" field (can I just set it to an empty string?) and what is the downside of doing this? I'm using SQL Server and ArcGIS Pro 3.1.1 (Windows)
... View more
09-18-2023
06:38 AM
|
0
|
2
|
501
|
POST
|
I ran into this same problem with JoinField - running with the python 3.9.16 that came with ArcGIS Pro 3.1.1. The documented workaround is to run the script in ArcGIS Pro but that really isn't an option for me.... Maybe I can accomplish what I need using a different type of Join.
... View more
09-15-2023
07:02 AM
|
0
|
0
|
892
|
POST
|
"displayName" can only be set in the getParameters method. From this page: Several properties, including name, displayName, datatype, direction, and parameterType, establish the characteristics of a tool and cannot be modified during validation methods (such as updateMessages and updateParameters).
... View more
09-08-2023
04:21 PM
|
1
|
1
|
328
|
POST
|
That string, when used in the query on line 15, should return information on all AGOL items owned by the specified user.
... View more
08-08-2023
12:39 PM
|
0
|
0
|
705
|
POST
|
I'm not sure if this will help, but I quite often need to create aprx files in my python code. The only way I've figured out is to use ArcGIS Pro to create an empty project and store it in the local file system where the python code can find it. The python code makes a copy of the aprx file then starts filling in the copy with maps layers or whatever.
... View more
07-27-2023
06:15 AM
|
0
|
1
|
248
|
POST
|
I would try to restructure the code roughly as follows: import sys, os, arcpy
import arcpy
## Works in file geodatabase
arcpy.env.overwriteOutput = True
workspace = "C:/temp/temp.gdb"
PR = "PrivateRoads"
CityLimits = 'City_Limits'
arcpy.MakeFeatureLayer_management(PR, "polyLyr")
arcpy.MakeFeatureLayer_management(CityLimits, "CitLyr")
arcpy.management.SelectLayerByLocation("polyLyr", "HAVE_THEIR_CENTER_IN", "CitLyr", "", "NEW_SELECTION")
pr_oid_to_city_name = dict()
# Add code here to use a search cursor scan the polyLyr and
# populate the dict that maps the pr oid to the city name
with arcpy.da.UpdateCursor(PR, ['OID@', 'Owner']) as cursor:
for oid, owner in cursor:
if oid in pr_oid_to_city_name.keys():
cursor.updateRow([oid, pr_oid_to_city_name[oid])
... View more
07-11-2023
04:34 PM
|
0
|
1
|
340
|
POST
|
I have had good luck with the "pip install spyder" technique on 2.9 and 3.0.3, described in a little more detail here.
... View more
06-23-2023
06:31 AM
|
0
|
0
|
319
|
POST
|
I solved this problem by storing my arcgis credentials in the keyring associated with my windows user id. The steps are: Sign into the windows system under the same windows ID that your script run under Store the arcgis credentials in the keyring. This is how I do it from the DOS window SET PYTHON_EXE=<path to your python.exe>
%PYTHON_EXE% -c "import keyring; keyring.set_password('<keyring id - used to retrieve password>', '<your arcgis user id>', '<your arcgis password>')" In your script you can now securely (only code running under your windows ID has access to the keyring) to retrieve those credentials and use them to sign into GIS instead of using "home" arcgis_user = <your arcgis user id>
arcgis_pw = keyring.get_password('<keyring id - used to retrieve password>', arcgis_user) You will have to remember to update the keyring by running the DOS commands whenever you change your password. The 'keyring id' can by any string that you make up.
... View more
06-17-2023
07:24 AM
|
2
|
0
|
265
|
Title | Kudos | Posted |
---|---|---|
1 | 03-06-2024 11:59 AM | |
1 | 12-11-2023 03:20 PM | |
2 | 11-17-2023 06:52 AM | |
1 | 10-12-2023 07:38 AM | |
1 | 10-01-2023 04:02 PM |
Online Status |
Offline
|
Date Last Visited |
2 weeks ago
|