Script Works in Python Window; Fails with AddInButton

1239
10
Jump to solution
09-12-2017 10:51 AM
JoeBorgione
MVP Emeritus

It's been 24 hours so Joe must have another Python question...

When I run the following in the python window it runs just fine:

with arcpy.da.SearchCursor(fc,fields) as rows:
 ...         streets = [row[1] for row in rows]
...          street = ",".join(["'{}'".format(s) for s in streets])
...          num = int(row[0])
...          max = num + 10
...          min = num - 10
...          where = "FullStreet = ({}) AND numeric_hn <=({}) AND numeric_hn >= ({})".format(street,max,min)
...          arcpy.SelectLayerByAttribute_management ("apLayer","ADD_TO_SELECTION",where)

I should add that I set fc = a given layer file in the arcmap session and fields is set to a list of two fields in the order of ["numeric_hn", "FullStreet"]

When I copy and paste this snippet in the addin.py file and click my button, it returns nothing.  When I run it with the python window open, I get this error:

Traceback (most recent call last):
File "C:\Users\JBorgione\AppData\Local\ESRI\Desktop10.5\AssemblyCache\{03EE6876-2D0C-48D0-86A4-147490A59723}\AddressAddIn_addin.py", line 21, in onClick
streets = [row[1] for row in rows]
IndexError: tuple index out of range

I don't understand why or how row[1] can be out of range, and I especially don't understand why it works in the python window and not when called by a button on a toolbar that has been created using the Addin Manager....

import arcpy
import pythonaddins

class ButtonClass1(object):
    """Implementation for AddressAddIn_addin.CreateLayerButton (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        arcpy.MakeFeatureLayer_management("SampleAddressPoints","apLayer")

class ButtonClass2(object):
    """Implementation for AddressAddIn_addin.RunCursorButton (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        fc = "apLayer"
        fields = ["numeric_hn","FullStreet"]
        with arcpy.da.SearchCursor(fc,fields) as rows:
            streets = [row[1] for row in rows]
            street = ",".join(["'{}'".format(s) for s in streets])
            num = int(row[0])
            max = num + 10
            min = num - 10
            where = "FullStreet = ({}) AND numeric_hn <=({}) AND numeric_hn >= ({})".format(street,max,min)
            arcpy.SelectLayerByAttribute_management ("apLayer","ADD_TO_SELECTION",where)
            
            

Thoughts?

That should just about do it....
0 Kudos
1 Solution

Accepted Solutions
DarrenWiens2
MVP Honored Contributor

I don't have an answer for you, but I'll suggest that you stick to the usual pattern of:

with arcpy.da.SearchCursor(fc,fields) as rows:
  for row in rows:
    # do things row by row‍‍‍‍‍‍‍‍‍

You can make your streets list, just once, before the creating the search cursor with a separate search cursor:

streets = [row[1] for row in arcpy.da.SearchCursor(fc, fields)]‍‍‍

At the very least, you're going to run into problems at the line "num = int(row[0])" because there is nothing called row anymore (row only exists within the scope of the list comprehension). I'm not sure why you didn't run into this problem in the Python window - you may have had a variable already called row...? edit: actually, this may only be a Python 3 thing, but the way it is now, row should be the final value in rows.

View solution in original post

10 Replies
DarrenWiens2
MVP Honored Contributor

I don't have an answer for you, but I'll suggest that you stick to the usual pattern of:

with arcpy.da.SearchCursor(fc,fields) as rows:
  for row in rows:
    # do things row by row‍‍‍‍‍‍‍‍‍

You can make your streets list, just once, before the creating the search cursor with a separate search cursor:

streets = [row[1] for row in arcpy.da.SearchCursor(fc, fields)]‍‍‍

At the very least, you're going to run into problems at the line "num = int(row[0])" because there is nothing called row anymore (row only exists within the scope of the list comprehension). I'm not sure why you didn't run into this problem in the Python window - you may have had a variable already called row...? edit: actually, this may only be a Python 3 thing, but the way it is now, row should be the final value in rows.

JoeBorgione
MVP Emeritus

I'm not sure why you didn't run into this problem in the Python window - you may have had a variable already called row...

Nope-  the only variables declared are fc and fields; I used an example straight off the online help pages so I had something I [knew] would work.  I'm such a bone-head when it comes to this stuff...

That should just about do it....
0 Kudos
DanPatterson_Retired
MVP Emeritus

Joe... can you explain why you aren't using a conventional toolbox and tools?  I am not sure why you have to make a featurelayer with the click of a button when conventional tools are much easier to maintain.  Is there some level of interactivity that isn't evident in your workflow?

JoeBorgione
MVP Emeritus

Dan- in this particular case I don't think creating a feature layer is a must; but....  being of newbie persuasion I'm just fumbling my way through all thi. The MakeFeatureLayer tool would certainly be a viable option, however with respect to the selection process, I'm not sure the SelectLayerByAttribute tool is applicable.  The selection process I'm deploying here is at the time based on a previously (and interactively) selected point.   Subsequently the cursor(s) are only scanning one whole record.

Stand by:  I'm sure to post a thread in the next 24 hours asking for help with a user provided parameter in the form of an entered address like "1234 S Main St" where I'll need tease out 1234 as the numeric house number, and S Main St as the FullStreet value...

All the best-

Dan Patterson

That should just about do it....
0 Kudos
DanPatterson_Retired
MVP Emeritus

ahhh. I didn't see the interactive selection part, since you were mentioning that your scripts worked standalone (aka... no interaction needed). and the latter would be too easy but too full of Vince Angelo‌'s optional and variant standards ( int("".join([i for i in a if i.isnumeric()])) ) to be worth pursuing

JoeBorgione
MVP Emeritus

Initially I've running everything in an ArcMap session, within the Python window, so the interactive selection is not apparent to you guys....  For now that's my 'standard'.....  

That should just about do it....
0 Kudos
VinceAngelo
Esri Esteemed Contributor

Oh, great, now I'm the keeper of the standards tontine of blame?  That will help me sleep at night.

- V

JoeBorgione
MVP Emeritus

We reap what we sow, brother....

That should just about do it....
0 Kudos
VinceAngelo
Esri Esteemed Contributor

Hey, I haven't created more than three or four, maybe five new standards. Well, unless you count... Let's say, no more than seven.

- V