ArcGIS Pro 2.3 - Proper syntax for codeblock in Python?

2906
8
Jump to solution
03-14-2019 09:13 AM
VincentLaunstorfer
Occasional Contributor III

Hi,

I have a tool based on y Python script which used to work perfectly in ArcGIS Desktop...

In Pro, it does not! In a CalculateField_management statement, I use the following codeblock to calculate the value to assign. In this case, it is a String and it looks like causing the problem (I have a similar statement with similar codeblock calculating integer value and it works fine).

Has the syntax for dealing with String changed slightly with Python 3 used in Pro? Something with single or double quotes? A combination of both?

Thanks

        codeblock_source = """def getSource(elev,user_source,source,ons_off):
          if elev != -9999 and ons_off == 'Onshore' and source == 'NA':
            return user_source
          elif ons_off == 'Offshore':
            return 'OFF'            
          else:
            return source"""
0 Kudos
1 Solution

Accepted Solutions
VincentLaunstorfer
Occasional Contributor III

Hi

The error was shown in the dialog box while running the script as:

<function GetMessages at 0x000002F1582FCAE8>

I don't know how to use traeback...

Anyway, I found the syntax error in the code. The return = 'OFF' within single quotes in the elif statment should be return = "OFF" within double-quotes. Silly but it took some time to figure out where the problem was from, among variables, codeblock, logic...

 codeblock_source = """def getSource(elev,user_source,source,ons_off):
 if elev != -9999 and ons_off == 'Onshore' and source == 'NA':
 return user_source 
 elif ons_off == 'Offshore':
 return "OFF"
 else:
 return source"""

It all works now! And it does mean there are some subtle difference in Python in ArcGIS Desktop and ArcGIS PRO...

View solution in original post

8 Replies
JoshuaBixby
MVP Esteemed Contributor

How exactly is it not working?  Is it giving you an error?  If so, what is the error and traceback if available.  If it is giving unexpected results, what is it giving and what do you expect?

curtvprice
MVP Esteemed Contributor

If you are working with this level of complexity and are not using Calculate Field in model builder, arcpy.da.UpdateCursor makes for much cleaner code.

That said, when I look at this code I see nothing that should not work in both Python 2 and 3. Are you sure the issue is the code block?

VincentLaunstorfer
Occasional Contributor III

Hi,

True, I could write my code with arcpy.da.UpdateCursor. I haven't thought about that.

In the meantime, I managed to fix my code!

Thanks

0 Kudos
VincentLaunstorfer
Occasional Contributor III

Hi

The error was shown in the dialog box while running the script as:

<function GetMessages at 0x000002F1582FCAE8>

I don't know how to use traeback...

Anyway, I found the syntax error in the code. The return = 'OFF' within single quotes in the elif statment should be return = "OFF" within double-quotes. Silly but it took some time to figure out where the problem was from, among variables, codeblock, logic...

 codeblock_source = """def getSource(elev,user_source,source,ons_off):
 if elev != -9999 and ons_off == 'Onshore' and source == 'NA':
 return user_source 
 elif ons_off == 'Offshore':
 return "OFF"
 else:
 return source"""

It all works now! And it does mean there are some subtle difference in Python in ArcGIS Desktop and ArcGIS PRO...

curtvprice
MVP Esteemed Contributor

I chalk this up to the very complex nested handling of strings required by using Calculate Field code blocks in a Python script. I do use Calculate Field in python scripts, but when a code block is needed as a rule I go to arcpy.da.UpdateCursor because the code is much easier to read (and of course, debug!).

flds = ["ELEV", "ONS_OFF", "SOURCE", "USER_SOURCE", "OFIELD"]
with arcpy.da.UpdateCursor(tbl, flds) as rows:
    for row in rows:]
        if row[:3] == ("-9999", "Onshore", "NA"):
            row[4] = row[3]
        elif row[1] == "Offshore":
            row[4] = "OFF"
        else:
            row[4] == row[2]
        rows.updateRow(row)
DanPatterson_Retired
MVP Emeritus

when mixing single and triple quotes in python, it is good to just dump the stuff in between them and examine how python tries to handle the quoting without having to 'escape' a quote character.

Examine the logic, it is important

# ---- assume for example that you have 1 pair of triple quotes """ """ or ''' '''

# ---- you add in 3 pairs of single quotes and 1 paire of double quotes

"""a 'b' 'c' 'd' "e" """

# ---- result, there is a bit of a struggle in python, so it escapes \ each single quote

'a \'b\' \'c\' \'d\' "e" '

# ---- so you make sure that you use only single quotes between the triple quotes

"""a 'b' 'c' 'd' 'e' """

# ---- result, there is no escaping necessary around the single quotes and the
# triple quote pair is just reduced to a pair of double quotes

"a 'b' 'c' 'd' 'e' "
0 Kudos
LukeWebb
Occasional Contributor III

Ive found that if I store the code in a temporary Microsoft Format. (Word, Excel etc)

The single quotes, are not compatible with some of the ESRI stuff.   But if you copy the same text into notepad, then copy that into Arc, many tools will work.

0 Kudos
VincentLaunstorfer
Occasional Contributor III

Probably. And it is totally normal.

For any script (such as Python in ESRI) or more substantial programming, ALWAYS use simple text editor and/or dedicated IDE program. These use plain text while any advanced text editor such as MS Word or others use rich text editing (with embedded formatting tags and so on).