I'm getting a "list index out of range" error and I don't know why. I'm parsing an address field to return only the street name. The following line gives the error:
elif prop_location.strip().split()[1] == 'S' or 'W':
return ' '.join(prop_location.strip().split()[2:-1]
According to the error log, the issue seems to be with the elif statement. This code has worked fine for a long time, but the last several times I've run it it has given me this error. I have checked the feature class for addresses that have a W or S with an index greater than 1, but I haven't found any. There are some records that are blank, and others without a 'W' or 'S', but they shouldn't be a part of this if statement. I'm not sure how to fix the code. Here is the all the code for context (problem statement is line 12). The error notification is added as an attachment:
def getStreetName( prop_location, Pre_Dir ):
if prop_location is None:
return None
elif prop_location == ' ':
return None
elif " #" in prop_location:
head, sep, tail = prop_location.partition(' #')
if head.strip().split()[1] == 'S' or 'W':
return ' '.join(head.strip().split()[2:-1])
else:
return ' '.join(head.strip().split()[1:-1])
elif prop_location.strip().split()[1] == 'S' or 'W':
return ' '.join(prop_location.strip().split()[2:-1])
else:
return ' '.join(prop_location.strip().split()[1:-1])
Solved! Go to Solution.
While looking at my code which I wrote over a year ago, I started wondering why I put 'Pre_Dir' in as a field that ocld be used. Then I realized that I already calculated the Pre_Dir in a previous step in the model. I substituted the problem line with the following line:
elif Pre_Dir == 'S' or 'W':
return ' '.join(prop_location.strip().split()[2:-1])
It worked like a charm. I obviously started out writing the code block with the intent use Pre_Dir in that fashion, but then forgot when I came to that portion of the code because I'm an airhead. Sincere thanks to Joe, Ian, Balaji, and Joshua. I'm still going to try out the usaddress package and let you know how it works in ModelBuilder.
Can you provide a value of prop_location that meets that elif conditional that is failing?
Sure, here are three different types of addresses that should be dealt with in the if statement:
1242 W 8550 S
1242 Bateman Ponds Wy
7726-7728 S 2700 W
Thanks for your help, Joe!
I run it in an IDE window and it works for me:
prop_location = '1242 W 8550 S'
>>> if prop_location.strip().split()[1] == 'S' or 'W':
print ' '.join(prop_location.strip().split()[2:-1])
# returns
8550
Check out this discussion I started a few years ago:
A better way to parse an address? It's a little different approach to parsing out Salt Lake Valley addresses.
Looking into my crystal ball, I see you working on the census address data for WJC....
Looking at your screenshot, it looks like the input it failed on was appeared to be a very large numbers of spaces or tabs. You look to have a condition to screen for a NULL value and for a single blank space, but not for multiple blank spaces or tabs.
Perhaps your first elif should be something like this:
elif prop_location.strip() == '':
return None
This would check for any amount of possible whitespace that could be in a field and if there are no other characters, return None.
This condition, expecting at least one space (' ') in prop_location value
> elif prop_location.strip().split()[1] == 'S' or 'W':
To avoid this error, try to skip the no space contained values by adding one more condition like
elif ' ' not in prop_location: return None
Don't reinvent a wheel that has already been made, and made fairly well in this case. Since you are only interested in parsing, and not validating, the addresses; there are several Python packages available for parsing addresses, particularly US-based addresses. One of them being usaddress - Parserator
>>> import usaddress
>>>
>>> address_string = '7726-7728 S 2700 W'
>>> address_dict = {v:k for k,v in usaddress.parse(address_string)}
>>> address_dict
{'StreetNamePostDirectional': u'W', 'StreetName': u'2700', 'StreetNamePreDirectional': u'S', 'AddressNumber': u'7726-7728'}
>>> for k,v in address_dict.items():
... print("{:40}:{}".format(k,v))
...
StreetNamePostDirectional :W
StreetName :2700
StreetNamePreDirectional :S
AddressNumber :7726-7728
>>>
This looks like it could really be helpful. My code is written in a 'Calulate Field' tool within a ModelBuilder model. This may be a dumb question, but does importing work in that environment? Can I simply import the usaddress package using the syntax above into that environment?
Not sure, I don't work with ModelBuilder. I know you can import modules in the code block of the Field Calculator, which leads me to believe you can do the same in ModelBuilder.
While looking at my code which I wrote over a year ago, I started wondering why I put 'Pre_Dir' in as a field that ocld be used. Then I realized that I already calculated the Pre_Dir in a previous step in the model. I substituted the problem line with the following line:
elif Pre_Dir == 'S' or 'W':
return ' '.join(prop_location.strip().split()[2:-1])
It worked like a charm. I obviously started out writing the code block with the intent use Pre_Dir in that fashion, but then forgot when I came to that portion of the code because I'm an airhead. Sincere thanks to Joe, Ian, Balaji, and Joshua. I'm still going to try out the usaddress package and let you know how it works in ModelBuilder.