Select to view content in your preferred language

Using Calculate Field in python?

1684
20
01-06-2011 08:18 AM
BartłomiejStaroń
Occasional Contributor
The tool works well in the MODEL bilder, but when it wants to convert it to the python script error occurs. All data from the column disappear.



import arcgisscripting
gp = arcgisscripting.create(9.3)
gp.workspace = "D:\\DATA.gdb\\"
TABLE = "D:\\DATA.gdb\\TABLE"
FIELD = "texx"

gp.CalculateField_management("TABLE", "FIELD", "StrConv([texx],vbUpperCase)", "VB")



What am I doing wrong??
0 Kudos
20 Replies
BartłomiejStaroń
Occasional Contributor
Script awfully long does this operation. He made 10 hours and did nothing.

Maybe there is a logical error that does not allow the script to be finished?
0 Kudos
BartłomiejStaroń
Occasional Contributor
After more checking the script. The script ends without showing the error.
However, nothing happens with the data.
0 Kudos
LukeBadgerow
Deactivated User
have you set the update script inside of a try/except block that passes off the messages from the geoprocessor i.e.

try:
     .... your update script here...
except:
    print gp.Messages(2)
    gp.AddError(gp.Messages(2))


The above code should alert you when something doesn't finish properly.  Otherwise there is a boilerplate error catch hosted someplace in the help topics for geoprocessing, I personally am phasing it out of all of my scripts in favor of "site specific" messaging on each piece of a script...
I'm wrapping anything that starts with gp into a try block, OR creating a method that returns just that result.
How many records are we talking about?  What kind of dataset are you connecting too?  I've seen issues where python thinks that the script is running successfully, but the server connection timed out and the dataset gets rolled back without update.

good luck
0 Kudos
ChrisSnyder
Honored Contributor
Apologies - I often just write the code out in the forum post without running it! This "should" work:

updateRows = gp.UpdateCursor("sfora_2")
updateRow = updateRows.Next()
while updateRow:
   newString = ""
   for word  in updateRow.MYFIELD.split(" "):
      newString = word.capitalize() + " " + newString
   updateRow.MYFIELD = newString[:-1]
   updateRows.updaterow(updateRow) #<<< THIS WAS THE MISSING LINE!
updateRow = updateRows.Next()
del updateRow
del updateRows
0 Kudos
ChrisSnyder
Honored Contributor
Apologies - I often just write the code out in the forum post without running it! This "should" work:

updateRows = gp.UpdateCursor("sfora_2")
updateRow = updateRows.Next()
while updateRow:
   newString = ""
   for word  in updateRow.MYFIELD.split(" "):
      newString = word.capitalize() + " " + newString
   updateRow.MYFIELD = newString[:-1]
   updateRows.updaterow(updateRow) #<<< THIS WAS THE MISSING LINE!
updateRow = updateRows.Next()
del updateRow
del updateRows
0 Kudos
BartłomiejStaroń
Occasional Contributor
Many thanks. The script works perfectly.
I just learn to write scripts. Still, not everything is so obvious to me:)

Now the script I will grow further.
0 Kudos
KimOllivier
Honored Contributor
Someone else just asked me the same thing. How about this one-liner?

gp.CalculateField_management(fc,"name","string.capwords(!name!)","PYTHON","import string")

(You have to import the string module because it's not a built-in string function.)

There may be other exceptions such as dashes and apostropies that need Uppercasing such as O'Brien or other Double-Banger names. In this case use a cursor and regular expression

import arcgisscripting
import string
import re
gp = arcgisscripting.create(9.3)

# settings
fc = "d:/work/test.gdb/trail"
# simple way but inadequate
gp.CalculateField_management(fc,"name","string.capwords(!name!)","PYTHON","import string")
print gp.GetMessages()

# Handle imbedded quotes like O'Brien
quoteabbrev = re.compile("'[a-z]")
# just as fast as a calculate and we can trap exceptions, errors
cur = gp.UpdateCursor(fc)
row = cur.next()
while row:
    x = string.capwords(row.name)
    if quoteabbrev.search(x):
        print x,name
        name = quoteabbrev.sub(quoteabbrev.search(x).group(0).upper(),x)
    cur.updateRow(row)
    row = cur.next()
del row,cur
print gp.GetMessages()


I never got the VB equivalent ProperCase to work in a script.
0 Kudos
LukeBadgerow
Deactivated User
Someone else just asked me the same thing. How about this one-liner?

gp.CalculateField_management(fc,"name","string.capwords(!name!)","PYTHON","import string")

(You have to import the string module because it's not a built-in string function.)

There may be other exceptions such as dashes and apostropies that need Uppercasing such as O'Brien or other Double-Banger names. In this case use a cursor and regular expression

import arcgisscripting
import string
import re
gp = arcgisscripting.create(9.3)

# settings
fc = "d:/work/test.gdb/trail"
# simple way but inadequate
gp.CalculateField_management(fc,"name","string.capwords(!name!)","PYTHON","import string")
print gp.GetMessages()

# Handle imbedded quotes like O'Brien
quoteabbrev = re.compile("'[a-z]")
# just as fast as a calculate and we can trap exceptions, errors
cur = gp.UpdateCursor(fc)
row = cur.next()
while row:
    x = string.capwords(row.name)
    if quoteabbrev.search(x):
        print x,name
        name = quoteabbrev.sub(quoteabbrev.search(x).group(0).upper(),x)
    cur.updateRow(row)
    row = cur.next()
del row,cur
print gp.GetMessages()


I never got the VB equivalent ProperCase to work in a script.



I believe that the benevolent dictator for life is recommending that you not use the string module.  You can now use the string methods to accomplish most of what I believe you are trying to do, for instance

columnValue = "hello world" 

columnValue.split(" ")

returnValue = columnValue[0].capitalize() + " " columnValue[1].capitalize()
print returnValue

>>>"Hello World"


Also it looks like you're trying to pass your entire coded returnvalue as a string:

gp.CalculateField_management(fc,"name","string.cap words(!name!)","PYTHON","import string")


Try it this way:

returnValue = columnValue[0].capitalize() + " " columnValue[1].capitalize()
gp.CalculateField_management(fc, "field", returnValue, "PYTHON")


My only other recommendation would be to NOT let the geoprocessor interpret code for you you aside from SQL if you can help it.  Let the native python do as much of the work for you as possible.
0 Kudos
ChrisSnyder
Honored Contributor
Seems there are many ways to skin this particular cat.
0 Kudos
KimOllivier
Honored Contributor
@csny490
I believe that the benevolent dictator for life is recommending that you not use the string module. You can now use the string methods to accomplish most of what I believe you are trying to do, for instance


I could not find any reference or discussion in the PEP's suggesting the string module will be deprecated. I did see an uninformed speculation in the year 2000 at version 1.5 thinking that it may happen after string functions were built-in. It is still there in 3.0, stonger than ever with the new string Template functions.
http://docs.python.org/py3k/library/stdtypes.html#string-methods

Since looking up the help I did find a better string function than string.capwords(<name>) called <name>.title() which does the same thing as capwords, but defines words as contiguous letters, so apostrophies and dashes are also counted as word boundaries (unlike capwords). This avoids using  regular expressions. The help does give an elegant example to handle special case exceptions using a generalised regular expression.

Therefore my one-liner can be even simpler and now handles name punctuation as is required for some strings such as roadnames. No need to import the string module even.

gp.CalculateField_management(fc,"name","!name!.title()","PYTHON")


Note that I do not have to handle variable numbers of words in the string, and there is no need to define a function in a block.
At Version 10 you can use Python expressions in the interactive field calculator to replace VB expressions so this would be very easy.

You will have to expand your comments regarding  returning entire strings, I don't want the strings returned and they are not, they are written directly into the featureclass if you use CalculateField.

"Letting the geoprocessor interpret code"? I have no idea what you are getting at.
0 Kudos