cursors and functions - ohio state university · cursors and functions gis 5222 jake k. carr week 5...

41
Cursors and Functions GIS 5222 Jake K. Carr Week 5 Cursors and Functions Jake K. Carr

Upload: others

Post on 02-May-2020

15 views

Category:

Documents


1 download

TRANSCRIPT

Cursors and Functions

GIS 5222

Jake K. Carr

Week 5

Cursors and Functions Jake K. Carr

Data Access

The ArcPy data access module (arcpy.da) allows us thefunctionality to access the data in a table - either an attributetable or a plain table.

We have seen how to iterate over the items in a list using loops.

In ArcPy we have a specific approach for the iterating over therows of a table: the cursor.

Cursors and Functions Jake K. Carr

Cursor

There are three types of cursors:

I Search Cursor: to retrieve rowsI arcpy.da.SearchCursor()

I Insert Cursor: to insert rowsI arcpy.da.InsertCursor()

I Update Cursor: to update or delete rowsI arcpy.da.UpdateCursor()

All of these cursors have two required arguments: an input tableand a list (or tuple) of field names1.

1Where would you find out more about the full syntax?Cursors and Functions Jake K. Carr

Search Cursor

The Search Cursor is used to pull data from a field or fields in atable.

Recall polygonVertices.py from last week. There, we pulled thepoint vertices that define the polygons from counties.shp from theShape field in the attribute table.

Let’s consider a much simpler example in which we pull the namesof each county in counties.shp. Note that county name is foundin the field COUNTY.

Cursors and Functions Jake K. Carr

Search Cursor

Here, we use the Search Cursor to pull data a list of county namesfrom the attribute table of counties.shp.

import arcpy

arcpy.env.workspace = r"C:\ GEOG5222\Lecture 2\Maps"

fc = "counties.shp"

with arcpy.da.SearchCursor(fc , ["COUNTY"]) as cursor:

for row in cursor:

print ("County Name = {0}".format(row [0]))

Note the use of the with arcpy.... as cursor: syntax. The with, asstatement tells python to open the table, perform the subsequentoperations, and then close the table upon completion of thoseoperations.

That way we don’t have to worry about shapefiles/feature classesremaining locked after we run our code.

Cursors and Functions Jake K. Carr

Insert Cursor

The Insert Cursor is used to insert a whole new row into a table.

Once the insert cursor is created we use the insertRow() method toinsert a list of values into the new record (row).

For demonstration purposes I have created a copy ofamtrak stations.shp and have simply called it:

amtrak stationsCopy.shp.

How did I make such a copy?

Cursors and Functions Jake K. Carr

Insert Cursor

Here, we create the Insert Cursor and use it to add a row to theattribute table of amtrak stationsCopy.shp.

import arcpy

arcpy.env.workspace = r"C:\ GEOG5222\Lecture 2\Maps"

fc = "amtrak_stationsCopy.shp"

cursor = arcpy.da.InsertCursor(fc , ["DESCRIPT"])

cursor.insertRow (["Scranton"])

del cursor

We are specifically adding the string value ‘Scranton’ to the fieldlabeled ‘Descript’ in the attribute table.

Add amtrak stationsCopy.shp to a map document to see if thenew value has been created.

Cursors and Functions Jake K. Carr

Insert Cursor

Note here that I did not use the with .... as cursor syntax.

That is because the InsertCursor does not support such syntax.

Therefore, we have to use the del cursor line at the very end toremove the ‘lock’ that ArcMap places on the shapefile.

Cursors and Functions Jake K. Carr

Update Cursor

The Update Cursor is used to update the values in a row or tocompletely delete a row from a table.

Once the update cursor is created we use the updateRow() methodto update a set of values in a particular record (row).

Alternatively, we can delete a particular row with the deleteRow()method - again, only after we have created the update cursor.

Cursors and Functions Jake K. Carr

Update Cursor

Here, we create the Update Cursor and use it to modify values inthe row that we have just added with the Insert Cursor.

import arcpy

arcpy.env.workspace = r"C:\ GEOG5222\Lecture 2\Maps"

fc = "amtrak_stationsCopy.shp"

with arcpy.da.UpdateCursor(fc , ["DESCRIPT", "AMTRAKX020",

"POINTID"]) as cursor:

for row in cursor:

if row[0] == "Scranton":

row[1], row [2] = 999, 1000

We are telling Python to find the row inamtrak stationsCopy.shp in which ‘DESCRIPT’ == ‘Scranton’,and then we update the values of the fields ‘AMTRAKX020’ and‘POINTID’ with the numbers 999 and 1000, respectively.

Cursors and Functions Jake K. Carr

Update Cursor

Finally, we create the Update Cursor and use it to delete the rowthat we have just modified with the previous Update Cursor.

import arcpy

arcpy.env.workspace = r"C:\ GEOG5222\Lecture 2\Maps"

fc = "amtrak_stationsCopy.shp"

cursor = arcpy.da.UpdateCursor(fc , ["DESCRIPT"])

for row in cursor:

if row[0] == "Scranton":

cursor.deleteRow ()

del cursor

Here, I haven’t used the with ... as cursor syntax since I am justsearching for one particular row and then deleting it with thedeleteRow() method.

Cursors and Functions Jake K. Carr

Functions

Functions are small blocks of code that perform a specific task.

We’ve already used some of the built in functions in Python (abs(),range(), etc.) and ArcPy (Describe(), ListFields(), etc.).

Sometimes we will want to write our own functions to automatespecific tasks for our geoprocessing application.

– We have already written some functions in Lab 1.

Cursors and Functions Jake K. Carr

Functions

Python functions are instantiated by the def statement.

We start the definition of a function with the syntax:

def functionname(arguments):

Recall that after the colon (:) we indent all subsequent lines ofcode to tell Python that these additional statements are part of thefunction.

Cursors and Functions Jake K. Carr

Function Example

Suppose we want to create a list of the names of all the fields inan attribute table.

Recall from Lecture 2 that the arcpy.ListFields function createssuch a list. We printed a list with the following commands:

>>> import arcpy

>>> arcpy.env.workspace = r"C:\ GEOG5222\Lecture 2\Maps"

>>> fieldnames = arcpy.ListFields("railroads.shp")

>>> for field in fieldnames:

print field.name

Cursors and Functions Jake K. Carr

Function Example

While arcpy.ListFields is nice, in that it allows us to access thecolumns of an attribute table, we see that we have to write a fewlines of code to actually get any of the output from arcpy.ListFields.

If we know that we will often use those same lines of code forvarious feature classes or shapefile (or basic tables) we might wantto package them up into our own function.

Cursors and Functions Jake K. Carr

fieldList Hard-Code

We start by writing the code to perform the operation on aspecified shapefile. This step is often called ‘hard-coding’.

import arcpy

arcpy.env.workspace = r"C:\ GEOG5222\Lecture 2\Maps"

fieldnames = arcpy.ListFields("railroads.shp")

namelist = []

for field in fieldnames:

namelist.append(field.name)

What will this code do?

Cursors and Functions Jake K. Carr

fieldList Function

To create a function that will produce the same results we start bydefining the function with the def statement. Note that everythingafter the def statement must be indented.

def fieldList(table):

fieldnames = arcpy.ListFields(table)

namelist = []

for field in fieldnames:

namelist.append(field.name)

In addition, we replace the ‘hard-coded’ value of railroad.shp withan argument variable, which we called ‘table’.

What assumptions does this code make?

Cursors and Functions Jake K. Carr

fieldList Function

The last thing that we need to do is to tell Python what thefunction should produce.

This is accomplished by using the return statement, which tellsPython that the object namelist should be output from thefunction.

def fieldList(table):

fieldnames = arcpy.ListFields(table)

namelist = []

for field in fieldnames:

namelist.append(field.name)

return namelist

Cursors and Functions Jake K. Carr

Using our fieldList Function

To use this function that we’ve written we simply call it like anyother function, supplying an appropriate ‘table’ argument:

>>> fieldList(r"C:\.....\ Maps\railroads.shp")

[u’FID’,

u’Shape’,

u’FNODE_ ’,

u’TNODE_ ’,

u’LENGTH ’,

u’RAILRDL020 ’,

u’RROWNER1 ’,

u’RROWNER2 ’,

u’RROWNER3 ’,

u’MARK1’,

u’MARK2’,

u’MARK3’]

Cursors and Functions Jake K. Carr

Using our fieldList Function

The whole purpose of functions is to reuse chunks of code.

If we wanted to get a list of fields from counties.shp we wouldjust use the fieldList function again:

>>> fieldList(r"C:\.....\ Maps\counties.shp")

[u’FID’,

u’Shape’,

u’AREA’,

u’PERIMETER ’,

u’CO2000P020 ’,

u’STATE’,

u’COUNTY ’,

u’FIPS’,

u’STATE_FIPS ’,

u’SQUARE_MIL ’]

Cursors and Functions Jake K. Carr

Function Arguments

Note that we have set an argument variable called ‘table’ in theconstruction of the function.

In the def fieldList(table): declaration we are telling Python toexpect one argument for our function, in this case the argumentvariable ‘table’.

Arguments are what is (sometimes) needed to run the function.

The sole purpose of this function it to create a list of fields from ashapefile or feature class, therefore we need to specify a featureclass or shapefile when we call the function in order to get a list offields from.

Cursors and Functions Jake K. Carr

Function Execution

The argument variable ‘table’ is just a place holder in the definitionof the function.

When we supply an argument to the function call, likefieldList(”railroads.shp”), Python replaces all instances of ‘table’with ‘railroads.shp’ and executes the following:

fieldnames = arcpy.ListFields("railroads.shp")

namelist = []

for field in fieldnames:

namelist.append(field.name)

return namelist

Cursors and Functions Jake K. Carr

Multiple Function Arguments

We can have more than one function argument:

def fieldListnum(table , number ):

fieldnames = arcpy.ListFields(table)

namelist = []

for field in fieldnames:

namelist.append(field.name)

return namelist [0: number]

Here number is a second argument that specifies how many fieldsto list.

Cursors and Functions Jake K. Carr

Multiple Function Arguments

The output will now depend on how we call the function:

>>> fieldListnum("railroads.shp", 5)

[u’FID’, u’Shape’, u’FNODE_ ’, u’TNODE_ ’, u’LENGTH ’]

>>> fieldListnum("railroads.shp", 4)

[u’FID’, u’Shape’, u’FNODE_ ’, u’TNODE_ ’]

Cursors and Functions Jake K. Carr

Optional Function Arguments

Arguments can also be made ‘optional’ by specifying a defaultvalue for them in the function def statement:

def fieldListnumOpt(table , number=None):

fieldnames = arcpy.ListFields(table)

namelist = []

for field in fieldnames:

namelist.append(field.name)

return namelist [0: number]

None is a special null keyword in Python. If we don’t specify asecond argument value, then that value will be set to None bydefault.

Cursors and Functions Jake K. Carr

Optional Function Arguments

Again, the output will depend on how we call the function:

>>> fieldListnumOpt("railroads.shp", 4)

[u’FID’, u’Shape’, u’FNODE_ ’, u’TNODE_ ’]

>>> fieldListnumOpt("railroads.shp")

[u’FID’,

u’Shape’,

u’FNODE_ ’,

u’TNODE_ ’,

u’LENGTH ’,

u’RAILRDL020 ’,

u’RROWNER1 ’,

u’RROWNER2 ’,

u’RROWNER3 ’,

u’MARK1’,

u’MARK2’,

u’MARK3’]

Cursors and Functions Jake K. Carr

Calling Functions From Other Scripts

Once we have a function that performs the desired operation(s) wecan use that function in one of two ways:

I Copy and paste the function code into our new script

I Save the function in its own script and ‘import’ the functionlike we have done with modules

Our choice will depend on how frequently we will use thisparticular ‘chunk’ of code. If this is a ‘one off’ function then we’lljust copy and paste. If this is a set of functionality that we willconsistently use, then we should save the function in its own script.

Cursors and Functions Jake K. Carr

fieldList.py

Let’s look at fieldList.py, which contains the code for the functionfieldListnumOpt:

def fieldListnumOpt(table , number=None):

import arcpy

fieldnames = arcpy.ListFields(table)

namelist = []

for field in fieldnames:

namelist.append(field.name)

return namelist [0: number]

You’ll notice that we have included the import arcpy commandinside the function definition - this is to ensure that the functionsfrom ArcPy are available for use when we call the fieldListnumOptfunction.

Cursors and Functions Jake K. Carr

Using fieldList.py

To activate the function(s) in fieldList.py we simply import it inthe usual way:

>>> import fieldList

Then we access the function fieldListnumOpt() in the usual way:with the module.functionname() syntax.

>>> fieldList.fieldListnumOpt("railroads.shp")

That means that we have created our own module!

Cursors and Functions Jake K. Carr

Where is my module?

Notice that we haven’t specified a directory location forfieldList.py

That’s because the import command does not support folder pathdesignation.

Therefore we need to know/understand where exactly Python‘looks’ for module scripts - those locations can be found with the‘system path’.

Cursors and Functions Jake K. Carr

Finding the System Paths

We can obtain a list of directories that Python uses for modulesusing the sys.path command:

>>> import sys

>>> for pth in sys.path:

print pth

C:\ Python27\ArcGIS10 .1\ DLLs

C:\ Python27\ArcGIS10 .1\lib

C:\ Python27\ArcGIS10 .1\lib\plat -win

C:\ Python27\ArcGIS10 .1\lib\lib -tk

C:\ Python27\ArcGIS10 .1

C:\ Python27\ArcGIS10 .1\lib\site -packages

C:\ Program Files (x86)\ ArcGIS\Desktop10 .1\bin

C:\ Program Files (x86)\ ArcGIS\Desktop10 .1\ arcpy

C:\ Program Files (x86)\ ArcGIS\Desktop10 .1\ ArcToolbox\Scripts

C:\ Python27\ArcGIS10 .1\lib\site -packages\win32

C:\ Python27\ArcGIS10 .1\lib\site -packages\win32\lib

C:\ Python27\ArcGIS10 .1\lib\site -packages\Pythonwin

Cursors and Functions Jake K. Carr

Import fieldList.py

Copy and paste fieldList.py into one of the above listed folderlocations2 and run:

>>> import fieldList

>>> fieldList.fieldListnumOpt(r"C:\...\ railroads.shp", 5)

[u’FID’, u’Shape’, u’FNODE_ ’, u’TNODE_ ’, u’LENGTH ’]

It’s just that easy.

2Your list will be different from those in above slideCursors and Functions Jake K. Carr

Alternatives to Copy/Paste

There are two other options besides copying the script module andpasting it in one of the designated folders.

I Create a path configuration file (.pth)

I Use the path append method

Cursors and Functions Jake K. Carr

Path Configuration File

A path configuration file (.pth) is just a text file that contains alist of alternate directory locations3.

Example: I have fieldList.py saved in C:\Carr \Modules, butC:\Carr \Modules is not in the list of system paths.

I’ll open up notepad and paste C:\Carr \Modules into an emptytext file. Save the file as mymodules.pth (with the .pth)extension) in one of the available system paths.

Note that these .pth files are typically saved in the site-packagesfolder.

3Not any of the locations already available from the sys.path callCursors and Functions Jake K. Carr

Path Configuration File

Also note that by default, ArcMap creates a path configuration fileupon installation.

This file is called something like Desktop10.1.pth and is locatedin the C:\Python27\ArcGIS10.1\Lib\site-packages folder.

Open it up and see what is inside, or use that default .pth file tostore all of your custom file directories!

Cursors and Functions Jake K. Carr

Append Path Method

Alternatively, we can temporarily add a folder location to ourPython session by using the path append method.

Go back to the above example: I have fieldList.py saved inC:\Carr \Modules. I can temporarily specifiy C:\Carr \Modulesas an available location by using the foloowing code:

>>> import sys

>>> sys.path.append(r"C:\Carr\Module")

Now I can access fieldList.py from C:\Carr \Modules. Note thatonce I close out of Python I lose access to that directory.

Cursors and Functions Jake K. Carr

Module Run Control

Now that we know how to access our script functions, we need totalk about controlling how those functions run.

If we import fieldList (as presented in the slide titled fieldList.py)then the function fieldListnumOpt will automatically run - which isthe default nature of running a script file.

More likely, we will not want the functions in our scripts to runautomatically, we will just want to make them available for use.

Cursors and Functions Jake K. Carr

Module Run Control

We can control how our functions run with the syntax:

if __name__ == ’__main__ ’:

fieldListnumOpt(table , number = None)

The (global) variable name tells python how to use the code inthe py-file.

If we import fieldList, then the value assinged to name will be‘fieldList’.

If we just open fieldList.py in IDLE and run it, then name willbe assigned the value ‘ main ’

Cursors and Functions Jake K. Carr

Module Run Control

The conditional statement:

if __name__ == ’__main__ ’:

fieldListnumOpt(table , number = None)

Says that if we are running the file fieldList.py as a script (inwhich case name == ‘ main ’) then run the functionfieldListnumOpt().

If that condition is not met (which means we imported fieldList.pyas a module) then Python knows not to run it and to make thefunctions inside available for use when called upon.

Cursors and Functions Jake K. Carr

The Complete Module

def fieldListnumOpt(table , number=None):

import arcpy

fieldnames = arcpy.ListFields(table)

namelist = []

for field in fieldnames:

namelist.append(field.name)

return namelist [0: number]

if __name__ == ’__main__ ’:

fieldListnumOpt(table , number = None)

Cursors and Functions Jake K. Carr

Using Our Module

We are all set to run it now:

# Import sys and append path to correct folder

>>> import sys

>>> sys.path.append(r"C:\Users\GEOG 5222\ Lectures\Lecture 4")

# Import fieldList module

>>> import fieldList

# Use fieldListnumOpt function from fieldList module

>>> fieldList.fieldListnumOpt(r"C:\Users\GEOG 5222\ Lectures\

Lecture 2\Maps\railroads.shp" ,5)

[u’FID’, u’Shape’, u’FNODE_ ’, u’TNODE_ ’, u’LENGTH ’]

Cursors and Functions Jake K. Carr