Patrick Brown-Iowa State University GIS Support and Research Facility
Howard Butler-Iowa State University Statistical Laboratory
After mastering the subtleties of VTab and FTab many ArcView users realize that Avenue alone can’t solve all of their challenges. Adding Python to the programmer’s toolbox can give ArcView access to the Internet, access to virtually any COM object with a published “IDispatch” scriptable interface, or perform other functions that just aren’t that easy to do with Avenue. This article will focus on a few examples and products that demonstrate the benefits of using Python and ArcView together.
Python is a portable, general-purpose, object-oriented programming language that works well with other programs or components. Best of all Python is free and in some ways looks very familiar to Avenue. It offers users the ability to create custom modules, classes, methods or functions. Python also allows programmers to “stand on the shoulders of others.” Modules provide a wide range of functionality such as database access, imaging libraries, network protocol usage, and XML parsing. What this means for the programmer is that a considerable amount of work has already been done.
Developed by Guido van Rossum, Python has been evolving for over ten years. It takes some of its features from a language called ABC, which was designed specifically to teach non-programmers about programming concepts. It also has features commonly associated with other programming languages such as object-oriented classes, exception handling, and dynamic data types. These features combined with internal consistency, readability and the fact that it “fits in your brain” make Python a powerful language.
In June of 2002, the authors of this article developed an ArcView extension called avTerra. It allows ArcView to act as a client to the Microsoft TerraServer (instead of downloading through a web browser), streamlining the process of getting TerraServer imagery into ArcView, and it provides nationwide DOQQ and DRG coverage at six resolution levels. avTerra utilizes a Web Service (SOAP) interface that TerraServer provides for programmers to develop applications, and was developed with Python and integrated into ArcView using AVPython.
avTerra could have been developed using Java, C/C++, or even Visual Basic, but Python had some features which made it very attractive to use with ArcView. First was the close integration of Avenue to a high-level scripting language via AVPython. This allows a user to call Python directly from ArcView and loop back to call ArcView from Python. Python also fulfilled other development requirements, as it had SOAP support, integration with COM, XML processing capabilities, and a full-featured imaging library called the PIL. Second, Python has a thriving user community that encourages participation and continually adds new capabilities to the language. Finally, it is a very developer-friendly language that does most of the heavy lifting and does not require the user to reinvent wheels every time a function is needed.
Another advantage is the ease of reading Python code. For example, Python uses indentation to define blocks within classes, functions, and various flow-control statements. In essence, the Python interpreter “just notices” the logical structure of the program. Consecutive lines that are indented the same way are part of the same block. Indentation makes revisiting code written a year ago in a language that might only be used occasionally much easier.
Python code is called from ArcView by loading the "Python Language Support" extension into the project. This extension was developed by Bruce Dodson, ESRI-Canada, and has been released under an open-source licensing agreement. The extension includes a number of scripts that can be called from an ArcView project in order to interface with Python. This article will focus primarily on the “Python.Exec” and “Python.Eval” scripts. Passing expressions to Python from an ArcView script is fairly easy—just call the appropriate Avenue script and pass it a string. The string can be used to import a Python module, call a Python function, or execute arbitrary Python code.
AVPython allows the Python
language to be embedded in ArcView. This integration is bi-directional.
Go to the Python site (www.python.org) and download Python 2.2, or go to ActiveState (www.activestate.com) and download ActivePython, a free commercial build of the Python core library plus some extra tools including support for COM and the Python IDE, an interactive programming window.
Scripts available to the
user after loading the AVPython extension.
Download and install the latest version of AVPython at http://avpython.sourceforge.net
Python.Exec:
Python code is executed in a "private" scope. Any local variables created by this code will be discarded when Python.Exec is next called. Returns 0 on success; -1 on error.
Python.Eval:
Evaluates a Python expression in the context of the last Python.Exec call, so all local variables from the previous call are available. A string is returned—if an error occurs, nil is returned.
Python modules are called by first importing a module; in this case, it is a module called “random” located in the /Lib directory where Python is installed. This is done by running the “Python.Exec” script and passing it the name of the Python module to import. This import exposes all of the methods and objects available in the “random” module. To import the “random” module so that the methods or objects can be called from ArcView create a new script and add the following line:
av.Run("Python.Exec",
"import random")
All of the methods and objects within the “random” module are now accessible. Next, a Python method will be called using the “Python.Eval” script. This evaluates the expression within the context of the last “Python.Exec” call. After Python evaluates the expression, a string is returned. Add the next couple of lines to the ArcView script, which calls the “randint” (random integer) function. The random integer function requires a minimum range value (1) and a maximum range value (100). It will return an integer within the specified range, which can be displayed using a message box. Enter the last two lines of the script and run the script.
theResult =
av.Run("Python.Eval", "random.randint(1,100)")
msgbox.info(theResult.AsString,"The random number is:")
‘randomSelect.ave
theView = av.GetActiveDoc
theTheme = msgbox.ListAsString(theView.GetThemes,"Choose a Theme"," Theme")
theFtab = theTheme.GetFtab
theNumRecs =
theFtab.GetNumRecords
'index range to pass to
the randint function
theMin = 0
theMax = theNumRecs - 1
'Evaluates the Python
script:
'random.randint(minimum
value, maximum value)
'passing the function the
theMin and theMax values. Values need to be 'passed as strings but will be
evaluated as integers by Python
av.Run("Python.Exec",
"import random")
theEvalStr ="random.randint("+theMin.AsString+","+theMax.AsString+")"
theResult = av.Run("Python.Eval",theEvalStr)
'make the selection on the
map using theResult
'which is returned from
the Python script
theBitMap =
Bitmap.make(theNumRecs)
theBitMap.Set(theResult.AsNumber)
theFtab.SetSelection(theBitMap)
theFtab.UpdateSelection
This example demonstrates the ability of being able to write scripts in Python and access them from ArcView. It also demonstrates that ArcView can be accessed from Python by importing a module called “arcview”. At this time the “arcview” module has one supported function called “avexec”. This runs the Avenue code and returns the result as a string. This can be used as a convenient way to access the ArcView object model, even if the bulk of the program is written in Python. This method can also be used to access global variables defined in Avenue.
For the next example, create a Python script by opening a text editor, or open the Python IDE and create a new script. Type the following, remembering that indentation matters in Python. Comments (#) can be excluded.
#avMessage.py
def infoBox(theString): #this function expects a string
from arcview import avexec
#regular Python scripts would import
#modules
at the beginning of the script
avexec('msgbox.info("'
+ theString + '","Message from Python")')
#calls
a message box from AV and inserts
#theString passed from the Avenue
script
Save the file as “avMessage.py” in the Python /Lib directory or in the same directory as the saved ArcView project. This file is a simple Python module called “avMessage,” and within the module is a function called “infoBox” which requires a string.
Notice the call to the “avexec” function. This function will open a message box with a string passed from ArcView. Now for the Avenue script to invoke Python:
‘script2.ave
‘string to pass to the
Python script
theString = "This
message box was called from Python"
‘import the avMessage
module you created
av.Run("Python.Exec",
"import avMessage")
‘execute the infoBox()
function you created in the avMessage module
‘the function expects a
string.
av.Run("Python.Eval", "avMessage.infoBox('" + theString + "')")
In summary, in the above Avenue script, the Python script avMessage.py is called, which passes a string to the “infoBox” function. Finally, the Python script opens up a message box in ArcView, printing the message.
This introduction to using Python with ArcView should give users a good foundation for designing ArcView applications, which integrate Python. There are a number of other examples worth exploring, each of which shows off some unique capabilities of using Python within ArcView. All of the examples can be accessed from the websites listed at the end of this article.
The AVPython package includes an example of pushing data into an Excel table using Python and COM rather than a DDE conversation.
avTerra
avTerra is an extension developed to access imagery available on the Microsoft Terraserver site. Images are tiled and brought directly into ArcView. All of this is done using Python modules that support XML and COM. Also used are the Python Imaging Library, the Microsoft SOAP Open Source Toolkit and Microsoft Terraserver’s SOAP API. Fortunately all of these are hidden from the user. Digging into the Avenue and Python code needed to create this extension will give users a good idea of the power and usefulness of using Python.
avTerra allows users to directly
import TerraServer images into ArcView.
For users of MySQL or other open source databases, the MySQL Connector demonstrates a non-ODBC method of querying and inserting data into a MySQL database from ArcView.
This demonstration allows a user to click on a map of the United States then access USGS real time stream gauge information. Python obtains the USGS stream gauge locations from an XML file generated by the website and the real time stream flow information is parsed from a an HTML table, both are then added to the ArcView project, joined, and added to the View as an event theme.
Python is used to create an
event theme from website data available in XML and HTML formats.
ArcView and Python together can be a powerful combination. Python provides an Avenue programmer a way to continue scripting to develop new functionality without resorting to lower level languages like C/C++. Python’s syntax is clean and feels comfortable to an experienced Avenue programmer. It also has cross-platform capabilities and a thriving user community. Digging through the examples mentioned in this article will give ArcView users a good start at integrating Python and ArcView.
Article Website (Download XML and HTML Scraper, example code and links) – www.gis.iastate.edu/python
Python – www.python.org
ActiveState Python – www.activestate.com/Products/ActivePython
AVPython Mailing List – groups.yahoo.com/group/avpython-dev/
AVPython (AVPython Extension, Excel Example) – avpython.sourceforge.net
avTerra (Download avTerra Extension) – hobu.stat.iastate.edu/avTerra
Patrick Brown is a GIS Analyst at the Iowa State University GIS Support and Research Facility.
Howard Butler is a GIS Analyst working at the Iowa State University Statistical Laboratory.
The authors wish to acknowledge Bruce Dodson, ESRI Canada, for his suggestions concerning this article and the continued development of AVPython.