第十一章 使用加载项自定义ArcGIS界面 ||| 附录A 自动执行Python脚本
我们将在本章介绍以下案例:
- 查看Python默认的错误消息
- 添加Python异常处理语句结构(try/except/finally)
- 调用GetMessages()函数获取工具消息
- 使用严重性级别筛选工具消息
- 调用GetMessage()返回单个消息
- 测试并响应特定错误消息
引言
ArcGIS地理处理工具和函数执行过程中会返回不同的消息。这些消息包括信息性消息,也可能含有提示警告信息或错误状况,这些警告或错误的出现意味着工具执行完毕后没有出现预期的结果或工具执行完全失败。不过这些消息并不是以消息框的形式显示,你需要调用许多不同的ArcPy函数来访问这些消息。到目前为止,我们都忽略了这些消息、提醒和错误。主要是因为希望你能专注于学习一些基本的概念,而没有增加额外的代码复杂度,而这些消息有关的代码对于创建能够处理错误状况的地理处理脚本是非常有必要的。现在是时候来学习如何在Python中创建异常处理语句结构。这些脚本可以处理在脚本执行过程中生成的提示警告信息,错误信息和通用信息。这些异常处理语句会让你的脚本更加灵活而且更不容易出现错误。你已经使用了基本的try
和except
语句块来执行一些简单的错误处理操作。在本章中,我们会介绍更多关于异常处理语句的细节内容。
查看Python默认的错误消息
默认情况下,Python在脚本中一旦遇到问题就会生成错误消息。这些错误消息的内容对于运行脚本的最终用户来讲并非总是那么明确具体。尽管如此,查看这些原始消息还是很有价值的。在后面的案例中,我们会使用Python错误处理语句结构来了解错误信息以及能够在必要时针对错误和异常情况作出反馈。
Getting ready
本案例中,我们会创建并运行一个有错误的脚本。在脚本中我们不会添加任何地理处理或Python异常处理结构。这样我们就能够看到Python自身返回的错误消息。
How to do it...
按照以下步骤来查看Python自身生成的错误消息,该消息是由于工具在执行过程中遇到错误生成的:
1.打开IDLE,创建一个新的脚本。
2.脚本保存为C:\ArcpyBook\Ch12\ErrorHandling.py
文件。
3.导入arcpy
模块:
import arcpy
4.设置工作空间路径:
arcpy.env.worksapce = "C:/ArcpyBook/data"
5.调用Buffer
工具。Buffer
工具需要一个缓冲距离作为其中一个参数。在代码中我们故意舍掉距离参数:
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
6.运行脚本。你会看到如下结果显示:
Traceback (most recent call last):
File "<string>", line 3, in <module>
arcpy.Buffer_analysis("Streams.shp","Stream_buffer.shp")
File "c:\program files\(x86)\arcgis\desktop10.1\arcpy\arcpy\analysis.py", line 687, in Buffer
raise e
ExecuteError: Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
How it works...
输出的错误消息中的内容似乎没什么有用的信息。如果是一个有经验的程序员,通常能够找到问题在于我们没有提供缓冲距离参数。然而,很多情况下,返回的错误消息并不会给你解决问题提供很多帮助信息。代码错误在编程中是不可避免的。如何理解这些称为异常的错误是非常重要的。你可以使用Python异常处理语句结构来有步骤地处理这些错误,而这些语句结构会查看arcpy
生成的异常信息并作出相对应的反馈。如果缺少这些语句结构,脚本在执行过程中很可能会随时中断或失败,从而让最终用户懊恼。
添加Python异常处理结构(try/except/finally)
Python内置的异常处理语句结构能够捕获脚本执行中生成的错误消息。你可以利用这些错误信息为最终用户提供一个更为明确的消息内容并在必要时候作出反馈。
Getting ready
异常是代码中的非正常或错误状况。异常处理语句能够捕获并处理代码中的错误,可以让程序能够从错误状况中恢复。除了用来处理错误,异常处理语句还可用于其他方面,比如事件提醒和特殊情况处理等。
Python的异常有两种发生方式。异常既可以捕获也可以触发。代码中发生错误时,Python会自动触发一个异常,这类异常有可能会在代码中处理。作为一名程序员需要捕获自动触发的异常。异常还可以通过代码方式进行人工触发。这种情况下,你需要提供一个异常处理机制来捕获这类人工触发的异常。你可以使用raise
语句来实现触发异常。
try/except
语句是Python中用来处理异常的一组完整的组合语句。try
语句结构是以try
作为首行代码,后面紧跟一组缩进的语句块,之后是一个或多个可选的except
语句用来命名捕获的异常,最后是一个可选的else
语句和finally
语句。
下面以try/except/else
语句结构来说明运行机制。在try
语句中,Python就会知道你现在正处于一个try
语句块中,一旦有异常发生就会直接交给后面的except
语句进行处理。try
语句块中的每一行代码都会执行。假如没有异常发生,代码就会跳至else
语句来执行else
语句中的代码然后再执行整个try/except/else
语句块后面的代码。如果有异常发生,Python会查找相匹配的异常语句,如果找到了匹配的except
语句,那么就会执行该except
语句中的代码,之后执行整个try/except/else
语句块后面的代码。在这种情况下else
语句则不会执行。如果没有找到匹配的except
语句,那么在这种情况下,异常提交给最高层try
语句中。这将导致一个无法处理的异常,也就会遇到我们在本章第一个案例中看到的错误消息。
本案例中,我们会添加一些基本的Python异常处理结构语句。在本案例中,我们先介绍一个非常简单的try/except
语句结构。
How to do it...
按照以下步骤在脚本中添加Python错误处理语句:
1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py
文件。
2.在脚本中添加try/except
语句:
import arcpy
try:
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
print "Error"
3.保存并修改脚本。你会看到一条简答的消息显示Error
。这条信息没有比我们在第一个案例中见到的结果更有帮助。事实上该消息的有用信息更少。本案例的目的只是介绍try/except
语句结构。
How it works...
这是一个非常简单的结构。try
语句块中的所有语句都会执行。如果异常发生,语句会跳至except
部分来打印错误消息,在本案例中也就是一个简单的Error
消息。如我之前所说,尽管这种消息对用户难言有价值,但希望可以让你对try/except
语句的工作方式有个基本了解,同时作为一名程序员,你需要更好地了解程序反馈的任何错误。在下一个案例中,你会学习如何在异常处理结构中获取由地理处理工具生成的消息。
There's more...
另外一种try
语句类型是try/finally
语句,该语句可用于执行终止操作。当finally
语句出现在try
语句块中使,无论是否发生异常或错误,finally
语句部分在最后都会执行。如果有异常发生,Python会执行try
语句块,之后执行finally
语句块,然后接着执行整个try
语句后面的代码。如果执行过程中没有出现异常,Python会执行try
语句块,之后执行finally
语句块。不管错误是否发生都需要确保执行某项操作时候,finally
语句会非常有用。
调用GetMessages()获取工具消息
ArcPy提供的GetMessages()
函数用于获取ArcGIS工具执行过程中生成的消息。这些消息既包括像工具执行的起始时间这样的信息性消息,也包括由于未得到预期结果或工具执行失败生成的警告信息和错误信息。
Getting ready
工具执行过程中会生成各种各样的消息。这些消息包括消息性消息,比如工具执行的开始和结束时间,工具使用的参数值以及进度消息。除此之外,工具还会生成警告消息和错误消息。这些消息可以通过Python脚本来读取,同时还可以编写代码来处理出现的警告或错误消息。
ArcPy会保存上一次执行的工具生成的消息,你可以调用GetMessages()
函数来读取这些消息,GetMessages()
会返回一个包含了工具在上一次执行中生成的所有消息的字符串。你可以使用严重性参数来筛选字符串以返回像警告消息或错误消息这样特定类型的消息。第一条消息通常是工具的名称,最后一条信息是工具执行的开始和结束时间。
在本案例中,你会添加一行except
语句,该语句用来打印关于当前运行工具执行过程中具体消息。
How to do it...
按照以下步骤来学习如何添加GetMessages()
函数来生成工具执行返回的消息列表。
1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py
文件。
2.添加GetMessages()
函数:
import arcpy
try:
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
print arcpy.GetMessages()
3.保存并运行脚本。这一次返回的错误消息应该会更为具体。你会注意到还有其他类型的消息返回,比如脚本执行的开始和结束的时间等。
Executing: Buffer c:/ArcpyBook/data\Streams.shp c:/ArcpyBook/data\Streams_Buff.shp # FULL ROUND NONE #
Start Time: Tue Nov 13 22:23:04 2012
Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
Failed at Tue Nov 13 22:23:04 2012 (Elapsed Time: 0.00 seconds)
How it works...
GetMessages()
函数返回上一次执行工具过程中生成的所有的消息。这里需要要强调的是该函数仅返回上一次执行的工具生成的消息。如果脚本中有多个工具执行的话那就需要留意这一点。历史记录中执行的工具过程生成的消息不能通过该函数获取。不过,你可以使用Result
对象获取历史记录中工具运行的信息。
使用严重性级别筛选工具消息
如前面提到的那样,所有的工具生成的消息可以分为消息性消息,警告消息和错误消息。GetMessages()
函数可接受一个严重性级别参数用来筛选返回的消息。举个例子,你可能只对工具执行过程中生成的错误消息感兴趣,对消息性消息和警告信息不感兴趣。调用GetMessages(2)
语句返回的消息中就仅包含错误消息。
Getting ready
任何消息都可以被归类到三种消息类型中一类中,消息类型可以通过一个严重性级别来指定。信息性消息(Informational messages)提供与工具执行有关的描述性信息,比如工具执行进度,工具执行的开始和结束时间,输出数据特征等等。消息性消息的严重性级别用数字0
来表示。警告消息(Warning messages)表示工具执行过程中出现的问题可能影响输出结果的时候生成。警告信息的严重性级别用数字1
表示,同时并不会中止正在执行的工具。最后一个类型是错误消息(error messages),该类型消息的严重性级别实用数字2
表示。错误消息表示有严重事件阻止工具运行。工具执行过程中会生成多个消息,这些消息都保存在列表中。更多关于消息严重性的信息见下图。在本案例中,你将学习如何调用GetMessages()
函数来筛选工具生成的消息。
How to do it...
筛选工具返回的消息非常简单。你只要将想要返回的严重性级别相对应的数字作为参数提供给GetMessages()
函数即可。
1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py
文件。
2.将数值2
最为参数传递给GetMessages()
函数:
import arcpy
try:
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
print arcpy.GetMessages(2)
3.保存并运行脚本会看到如下结果:
Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
How it works...
如前所述,GetMessages()
函数可接受0
,1
,2
整数值参数。数值0
表示返回消息性消息,而数值1
表示返回警告消息。在本案例中,我们使用数值2
表示我们只关注错误消息。这样你在输出结果中就不会看到脚本执行的开始和结束时间这样的信息性消息。
测试并响应特定错误消息
所有的错误和警告都会生成一个特定的错误代码。我们可以在脚本中来检查特定的错误代码,并基于这些错误代码来执行特定的操作。
Getting ready
地理处理工具的返回的错误和警告都包含一个六位数字代码和一条描述性信息。你在脚本中可以检测特定的错误代码并作出相应地反馈。你可以在ArcGIS帮助系统中的地理处理|工具错误和警告(Geoprocessing|Tool errors and warnings)中看到包含所有错误消息和代码的列表。如下图所示,所有的错误根据错误代码都有一个对应的描述页面:
How to do it...
按照以下步骤来学习如何编写代码来响应地理处理工具执行过程中生成的特定的错误代码:
1.点击开始|所有程序|ArcGIS|ArcGIS Desktop 10帮助
(Start|Programs|ArcGIS|ArcGIS for Desktop Help)打开帮助系统。
2.找到地理处理|工具错误和警告|工具错误1-10000|工具错误和警告:701-800(Geoprocessing|Tool errors and warnings|Tool errors 1-10000|Tool errors and warning:701-800)。
3.选择000735:<值>:需要值(000735:<value>:value is required)。该错误提示没有提供工具需要的必选参数。我们在脚本中没有提供缓冲距离参数导致了错误消息产生,其中包括了我们在帮助系统中看到的错误代码(000735)。下面的消息代码中,你会发现完整的错误消息文本。留意错误代码(000735)。
ERROR000735:Distance[value or field]:Value is required
4.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py
文件。
5.如下所示修改脚本代码:
except:
print "Error found in Buffer tool \n"
errCode = arcpy.GetReturnCode(3)
if "735" in str(errCode):
print "Distance value not provided \n"
print "Running the buffer again with a default value \n"
defaultDistance = "100 Feet"
arcpy.Buffer_analysis("Steams.shp","Streams_Buff.shp",defaultDistance)
print "Buffer complete"
6.保存并运行代码。你会看到如下消息:
Error found in Buffer tool
Distance value not provided for buffer
Running the buffer again with a default distance value
Buffer complete
How it works...
我们在代码中调用了arcpy.GetReturnCode()
函数来返回工具生成的错误代码。之后if
语句用来检测错误代码中是否包含数值735
,该代码表示错误是由于没有提供工具必选参数造成。接下来我们提供了一个缓冲距离值并再次调用Buffer
工具。
调用GetMessage()函数返回单个消息
GetMessages()
会返回上一次工具运行时生成的全部消息列表,不过你可以调用GetMessage()
函数来获取其中的单个消息。
Getting ready
到目前为止,我们都是返回工具生成的全部消息。不过,你可以调用GetMessage()
函数为用户返回单个消息,该函数接受一个整型参数来指定要返回的特定消息。工具生成的消息都是位于消息列表或数组中。
这里提醒一下,列表是零值开始计算索引值的,也就意味着了列表中的第一个元素的位置为0
。比如,GetMessage(0)
会返回列表中的第一条信息,而GetMessage(1)
则返回第二条信息。第一条消息通常是当前运行的工具名称以及参数信息。第二条消息返回脚本运行的开始时间,而最后一条消息则返回脚本的结束时间。
How to do it...
1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py
文件。
2.如下所示修改代码:
import arcpy
try:
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
print arcpy.GetMessage(1)
print arcpy.GetMessage(arcpy.GetMessageCount()-1)
3.保存并运行脚本,你会看到如下结果显示:
Start Time: Wed Nov 14 09:07:35 2012
Failed at Wed Nov 14 09:07:35 2012 (Elapsed Time: 0.00 seconds)
How it works...
我们之前没有介绍GetMessageCount()
函数。该函数返回工具生成的消息数量。记住消息列表是从零值开始索引,因此我们需要从GetMessageCount()
返回的结果中减去1来获取列表中的最后一条消息。否则的话,我们就是在试图访问列表中不存在的消息。在本案例中,我们获取了脚本执行的开始和结束时间。第二条消息通常是脚本执行的开始时间,而最后一条消息则是脚本执行的结束时间。下面的返回结果中则说明了这个问题:
Message 0 - Executing: Buffer c:/ArcpyBook/data\Streams.shp c:/ArcpyBook/ data\Streams_Buff.shp # FULL ROUND NONE #
Message 1 - Start Time: Tue Nov 13 22:23:04 2012
Message 2 - Failed to execute. Parameters are not valid.
Message 3 - ERROR 000735: Distance [value or field]: Value is required
Message 4 - Failed to execute (Buffer).
Message 5 - Failed at Tue Nov 13 22:23:04 2012 (Elapsed Time: 0.00 seconds)
全部消息的数量为6
,但是最后一条消息对应的索引数为5
。这也就是为什么我们要在脚本代码中减去1
的缘故。本案例中,由于脚本中发生错误,因此开始和结束时间相同。尽管如此,该案例仍然说明了如何来获取由工具生成的单个消息。