Passing a number variable as global in python

1632
9
09-07-2017 10:52 AM
DuminduJayasekera
New Contributor III

Hi,

I want to loop the below process for multiple years so tested with one year. I am getting an error when it tries to change the (YEAR) as calculate field as a number variable with the corresponding year. Cannot understand what I am doing wrong here. Everything else up to line 29 is working. Problem is inside the code block section. 

Any help is greatly appreciated. 

Thanks in advance. 

ExecuteError: ERROR 000539: Error running expression: getClass(1998.0) 
Traceback (most recent call last):
  File "<expression>", line 1, in <module>
  File "<string>", line 4, in getClass
NameError: global name 'yr' is not defined

Failed to execute (CalculateField).
‍‍‍‍‍‍‍

years = [1997] 
# Write the selected features to a new featureclass
for year in years:
 arcpy.CopyFeatures_management("PLSS_KS_All_GCS", r"C:/Users/Desktop/Flood/KS_All.gdb/PLSS_KS_All_WklyPrSum_PRISM_800m_" + str(year)+ "_new")

 # Set environment settings
  arcpy.env.workspace = "H:/PRISM_800m_weekly_sum_tif" 
 
# Set local variables
 inPointFeatures = r"C:/Users/Desktop/Flood/KS_All.gdb/PLSS_KS_All_WklyPrSum_PRISM_800m_" + str(year)+ "_new.shp"

 
# Set local variables
 inRasterList = [["Week_1_Sum" + str(year)+ "_10.tif", "Oct_PCPwk1"], 
 ["Week_2_Sum" + str(year)+ "_10.tif", "Oct_PCPwk2"], 
 ["Week_3_Sum" + str(year)+ "_10.tif", "Oct_PCPwk3"],
 ["Week_4_Sum" + str(year)+ "_10.tif", "Oct_PCPwk4"],
 ["Week_5_Sum" + str(year)+ "_10.tif", "Oct_PCPwk5"],
 ["Week_1_Sum" + str(year)+ "_11.tif", "Nov_PCPwk1"],
 ["Week_2_Sum" + str(year)+ "_11.tif", "Nov_PCPwk2"]]
  
 
 # Check out the ArcGIS Spatial Analyst extension license
 arcpy.CheckOutExtension("Spatial")

# Execute ExtractValuesToPoints 
 ExtractMultiValuesToPoints(inPointFeatures, inRasterList, "BILINEAR") #NONE
 
 
 fieldName = "YEAR"
 expression = "getClass(!YEAR!)"
 codeblock = """def getClass(YEAR):
 global yr
 yr=1997
 if YEAR >= 1998:
 return yr
 else:
 return -9999"""
 
 # Execute AddField
 #arcpy.AddField_management(inTable, fieldName, "SHORT")
 
 # Execute CalculateField 
 arcpy.CalculateField_management(inPointFeatures, fieldName, expression, "PYTHON_9.3", codeblock)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
9 Replies
DanPatterson_Retired
MVP Emeritus

in your code block, try putting 

yr = -9999 

on a new line before the def line

you have to initialize yr before you can make it global

0 Kudos
DuminduJayasekera
New Contributor III

Thanks Dan for the reply. I did as you suggested but still getting the same error. Please see the revised error message and code above. 

0 Kudos
DarrenWiens2
MVP Honored Contributor

I think you need to initialize yr inside the codeblock string. The variables inside the codeblock don't communicate with those in the main script.

0 Kudos
DuminduJayasekera
New Contributor III

OK. I updated the code inside the code block manually to reflect what you suggested and it worked. (Please see the revised code above). But, I need to pass the value in "year" in the main script into the code block. For example in this case 1997. I need to avoid manually enter the year into the code block so I can run the script for multiple years. How can I achieve that?

0 Kudos
DanPatterson_Retired
MVP Emeritus

It could be a code formatting issue or something, but I would suggest at this point, that you test your field calculator expression by doing it manually in the Calculate Field, then go to the Results Window and copy the code block exactly... the spaces and newline characters or presence must be able to form a correct def before it will work

0 Kudos
DuminduJayasekera
New Contributor III

Dan. I did what you suggested to test manually (Please see the code above and it works). But I need to pass "year" into the code block in the main script. 

0 Kudos
KE
by
Occasional Contributor

You could do this with a cursor instead of field calculator:

# Define search cursor
urows = arcpy.da.UpdateCursor(inPointFeatures, "YEAR")
# Loop through each row in cursor
for urow in urows:
    # If the value for YEAR is greater than or equal to 1998 yr is 1997
    if urow[0] >= 1998:
        yr = 1997
    # If not yr is -9999
    else:
        yr = -9999
    # Update the YEAR attribute for this row
    urow[0] = yr
    urows.updateRow(urow)
# yr variable is available outside for loop
print yr‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

UpdateCursor—Help | ArcGIS for Desktop  

0 Kudos
RandyBurton
MVP Alum

As Dan Patterson‌ mentioned, some of you issues may be with formatting.  The indentation is not very clear from the code posted.

In line 41 you are creating a new field "YEAR", and in line 44 you are using the codeblock to populate that new field. Since the new field is set to null, the codeblock section probably isn't doing a valid comparison.  I would suggest removing the codeblock and replacing the expression with the year.

year = 1997 # this is essentially year from the loop

# Execute CalculateField 
arcpy.CalculateField_management(inPointFeatures, fieldName, year, "PYTHON_9.3", "#")
DuminduJayasekera
New Contributor III

@Randy. Thanks it worked. 

0 Kudos