Select to view content in your preferred language

Python script if/for/while

6076
22
Jump to solution
07-09-2015 09:46 AM
CoyPotts1
Deactivated User

*UPDATE*

For samples of the correct code, see posts below.

I'll start off by apologizing for not having any sort of sample of my code, but I am really just unsure on how to begin the code, so all I have is notes of what I need.

I have a feature class that has a number of fields that are duplicated for 5 different customers.  The fields that I need to focus on in this exercise are the Cust1Name, Cust1NodeID, Cust1HomeID, and 10 Cust1CircuitID fields.  I'm using "Cust1", "Cust2", etc only as examples in place of their actual names...just stating that to eliminate your efforts in trying to add the customer number in a potential for/while loop.  Essentially the fields look as they do below:

Cust1Name

Cust1NodeID

Cust1HomeID

Cust1CircuitID1

...

Cust1CirctuitID10

Cust2Name

Cust2NodeID

Cust2HomeID

Cust2CircuitID1

...

Cust2CircuitID10

etc...

My feature class has fields for all 5 customers, but not all 5 will be populated.  I've used the Cust#NodeID field as my reference for whether calculations will run or not because that field determines if they are needed or not.  Populated means run the calculation, while Null means do nothing.

if Cust1NodeID != None:
     return # insert calculation here
else:
     return None

I also need to get a users input to know the amount of circuit ID's needed.  The number varies from 1 to 10 circuit ID's.

numberIDs = arcpy.GetParameterAsText(0)

With this information I need the script to go through each Cust#NodeID field to check and see if it's null or not.  If it's null, keep moving...if it has data, calculate the amount of circuit ID fields needed based on the input.


Again, sorry for having nothing to start with.  I'm just confused on which route to take (for loop, while loop, if/if...), and I can't figure out any of them either way.  I'm just not sure how to add so many arguments together.

*EDIT*

I'll also note that the circuit ID calculation itself is just a concatenation of the given fields, as shown below:

Cust1CircuitID1 = (Cust1Name) - (Cust1NodeID) - (Cust1HomeID) - (01)

Cust1CircuitID2 = (Cust1Name) - (Cust1NodeID) - (Cust1HomeID) - (02)

etc...

0 Kudos
22 Replies
DarrenWiens2
MVP Honored Contributor

First error: you need a colon after the elif statement.

elif (numIds == 2):

Second error: I don't believe '&' is a valid Python operator. Use 'and' instead at both places.

if (row[0] != None) and (numIDs < 2):

DanPatterson_Retired
MVP Emeritus

too much NumPy ... you are right

0 Kudos
CoyPotts1
Deactivated User

The colon was missing only in entry error...I manually typed out the code because whenever I try to paste into the syntax highlighter it ends up cutting off pieces.  (I just tested and realized that you could paste the code first and then apply the syntax highlighting...doh!  Nothing like a simple mistake to make you feel dumb)

I only used "&" because that's what Dan used in his examples.  I substituted "and" in the same sample that was using "&", and I get the same error message:

"Runtime error

Traceback (most recent call last):

  File "<string>", line 16, in <module>

TypeError: coercing to Unicode: need string or buffer, NoneType found"

0 Kudos
DarrenWiens2
MVP Honored Contributor

I suspect the problem is trying to write null values, but haven't tested it.

for row in cursor:  
    if (row[0] != None) and (numIDs < 2):  
          row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"  
    elif (row[0] != None) and (numIDs < 3):  
          row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"  
          row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)" 
    else:
       pass # do nothing and move to next row

    cursor.updateRow(row) 
CoyPotts1
Deactivated User

I tried your suggestion with the same three scenarios as shown in my response to Dan (below), and I got the following results in order from top example to bottom:

Example 1:

"Runtime error

Traceback (most recent call last):

  File "<string>", line 17, in <module>

TypeError: coercing to Unicode: need string or buffer, NoneType found"

Example 2:

"Runtime error

Traceback (most recent call last):

  File "<string>", line 16, in <module>

TypeError: coercing to Unicode: need string or buffer, NoneType found"

Example 3:

Same as explained in my response to Dan where it seems like nothing really happens.

0 Kudos
DarrenWiens2
MVP Honored Contributor

You can't concatenate strings and numbers. To convert numbers to strings, use str():

row[3] = "(" + str(row[2]) + ") - (" + str(row[0]) + ") - (" + str(row[1]) + ") - (01)"

CoyPotts1
Deactivated User

That did the trick.  I tried with a variable of 1 and 2, and both returned the desired results.  Many thanks!  I used the code pasted below:

for row in cursor:
     if (row[0] and numIDs < 2):
          row[3] = "(" + str(row[2]) + ") - (" + str(row[0]) + ") - (" + str(row[1]) + ") - (01)"
     elif (row[0] and nuIDs <3):
          row[3] = "(" + str(row[2]) + ") - (" + str(row[0]) + ") - (" + str(row[1]) + ") - (01)"
          row[4] = "(" + str(row[2]) + ") - (" + str(row[0]) + ") - (" + str(row[1]) + ") - (02)"
     else
          pass
     cursor.updateRow(row)

I'm a little confused why you have to designate it as a string only because I thought it was grabbing the actual value from the row reference.  I didn't realize the program read the number literally, but rather thought it SAW row[0] and THOUGHT NodeID field.

Either way, it works and you have helped me once again!

0 Kudos
DarrenWiens2
MVP Honored Contributor

It is grabbing the actual value from the row reference, but if the value comes from a numeric field it will be cast as numeric Python data type (int, long, or float, as appropriate), which is quite amazingly different from a Python string, which is actually a sequence (like a list).

DanPatterson_Retired
MVP Emeritus

None null, none, nadda can be trapped by a truth test rather than a comparison test:

>>> vals = [None,1,2,3]
>>> for val in vals:
...  if val:
...   print "val is"
...  else:
...   print "val isn't"
...   
val isn't
val is
val is
val is
>>>

So perhaps you should be looking at getting rid of your ...if row[0] != None: stuff and just using    if row[0]:

CoyPotts1
Deactivated User

I used your suggestion on all previous versions of the code and none worked. 

(param1 and param2)

for row in cursor:
        if (row[0] and numIDs < 2):
            row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"
        elif (row[0] and numIDs < 3):
            row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"
            row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)"
        cursor.updateRow(row)

Returns this errors:

"Runtime error

Traceback (most recent call last):

  File "<string>", line 16, in <module>

TypeError: coercing to Unicode: need string or buffer, NoneType found"

(param1) and (param2)

for row in cursor:
        if (row[0]) and (numIDs < 2):
            row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"
        elif (row[0]) and (numIDs < 3):
            row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"
            row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)"
        cursor.updateRow(row)

Returns the same error to the letter.

And Lastly:

if param1

     if param2

for row in cursor:
        if row[0]:
            if numIDs < 2:
                row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"
        elif row[0]:
            if numIDs < 3:
                row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)"
                row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)"
        cursor.updateRow(row)

This one doesn't seem to do anything.  I'm not even sure if it runs.  It doesn't kick back an error, but it also doesn't update the fields.

0 Kudos