可以编写以多种方法执行和使用地理处理服务的 Python 脚本。执行脚本的主要方法是使用 ArcPy。ArcPy 内置了用来连接、执行和处理服务结果的方法。此外,使用服务目录可以通过内置的 Python 模块调用使用 JSON 结构的 REST,以便传输结果。 您将需要使用 Python 代码在临时工作空间构建客户端以便使用 ArcPy。大多数脚本均通过 ArcPy 来连接和使用地理处理服务。
ArcPy 方法
在 ArcMap 中,可以通过 Python 窗口(脚本工具或独立的脚本)来访问地理处理服务。URL 用于连接和使用地理处理服务。
使用 ImportToolbox 连接服务。
# arcpy.ImportToolbox("http://<hostname>:<port>/arcgis/services;<optional folder>/<service name>","<optional alias>")
arcpy.ImportToolbox("http://degrassi:6080/arcgis/services;GPFolder/BufferService","PointAlias")
用于导入该工具的路径是地理处理服务的 URL。ImportToolbox 接受两个参数:该服务的 URL 和可选的工具箱别名。URL 参数分为使用分号 (;) 隔开的两部分。第一部分是服务端点 URL(或链接),第二部分是服务名称(可选,文件夹名称在服务名称之前)。
地理处理服务既可以同步执行,也可以异步执行。作为 Python 脚本编写者,您需要了解如何执行服务才能使用服务。IsSynchronous 属性可用来确定服务的执行类型。当同步执行服务时,会自动返回结果,但在服务结束之前不能执行任何操作。当异步执行服务时,必须定期查询当前执行状态。完成服务执行后,可以访问结果。
下列 Python 代码显示了如何连接到异步地理处理服务以及如何使用 ArcPy 功能来执行服务、获取结果和进一步处理服务。通过在执行任务时设置结果变量,可使用 While 循环检查状态。返回状态码 4 (成功)或更高状态码时,表示任务完成。
使用异步 GP 服务创建缓冲区并在本地保存结果
import arcpy
import time
arcpy.ImportToolbox("http://sampleserver1.arcgisonline.com/ArcGIS/services;Elevation/ESRI_Elevation_World", "viewshedAlias")
result = arcpy.Viewshed_viewshedAlias(r'c:\data\inputPoint.shp', "10000 Kilometers")
while result.status < 4:
print result.status
time.sleep(0.2)
print "Execution Finished"
result.getMessages()
arcpy.CopyFeatures_management(result.getOutput(0), 'localResult.shp')
有关结果对象和状态码及创建栅格和地图图像输出的详细信息,请参阅帮助主题在 Python 使用工具。
RESTful 方法
使用地理处理服务的另一个方法(但不常用)是通过构建用于执行 REST 调用的应用程序,同时使用 JSON 作为数据交换格式。此方法要求编写发送请求和处理响应的代码。
由于必须自行处理所有输入和输出语法,因此 REST 消息的发送和接收较为复杂。REST 消息的发送和接收的优点在于这些消息能够以一致方式返回。请求可以通过 HTTP GET 方法发送,而响应则以 JSON 结构返回。核心 Python 库同时支持发送 HTTP GET 请求和函数,这更易于读取和解析 JSON 消息。
下例使用 Esri 示例服务器上的服务,并说明如何连接服务、发送请求和处理响应。
提交请求
例如,SampleServer1 包含用于创建视域的地理处理服务,并且可以从 http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation 中访问。此服务采用点和距离作为输入,并返回要素集。下列输入有助于更好地了解该服务:
参数名称 | 输入值 |
---|---|
输入观测点 (GPFeatureRecordSetLayer) | {"geometryType" :"esriGeometryPoint", "spatialReference" :{"wkid" :54003}, 'features':[{'geometry':{'x':-13308192.1956127, 'y':4221903.58555983}}]} |
视域距离 (GPLinearUnit) | { 'distance' :8.5, 'units' :'esriMiles' } |
格式(输出使用的格式) | JSON |
此请求将从服务中返回可见位置的 JSON。用于生成该请求的完整 URL 可在 Web 浏览器地址栏中使用。
http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed/execute?Input_Observation_Point={%22features%22%3A[{%22geometry%22%3A{%22x%22%3A-13308192.1956127%2C%22y%22%3A4221903.58555983}}]}&Viewshed_Distance={+%27distance%27+%3A+8.5%2C+%27units%27+%3A+%27esriMiles%27+}&env%3AoutSR=&env%3AprocessSR=&f=pjson
使用 Python 模块 Urllib 或 Urllib2 可以提交 URL。下列 Python 代码将以使用服务目录或将链接复制到 Web 浏览器地址栏的类似方法来执行上述请求。
import urllib
import json
inPts = {"geometryType" : "esriGeometryPoint",
"spatialReference" : {"wkid" : 54003},
'features':[{'geometry':{'x': -13308192.1956127,'y': 4221903.58555983}}]}
dist = {'distance':8.5,'units':'esriMiles'}
data = {'Input_Observation_Point': inPts,
'Viewshed_Distance': dist,
'f': 'pjson'}
URL = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed/execute'
result = urllib.urlopen(URL, urllib.urlencode(data)).read()
print json.loads(result)
结果对象以字符串格式返回。共有多种生成请求和解析结果的方法;上例仅是其中一种方法。使用 json.loads() 方法可以将地理处理服务中返回的 JSON 放到字典中,如上例所示。根据地理处理服务的输出,这可能是最佳技术,否则,在 Python 中通过 REST 使用地理处理服务时,可能需要浏览其他选项来处理地理处理服务的输出。
注:
如果使用结果要素,则确保使用实际 x,y 坐标对对工作流有意义,因为您将无法以支持 ArcGIS 内部几何的格式接收实际要素。
异步执行的服务要求定期请求任务状态,以便查看是否完成任务,这与上述使用 ArcPy 的示例类似。Python 代码可能在检查作业状态时返回的 JobStatus 状态消息中查找 EsriJobSucceeded 或 esriJobFailed 短语。下列代码示例表示使用异步地理处理服务(使用 SubmitJob)的一项技术。
import urllib, json, time
inPts = {"geometryType" : "esriGeometryPoint",
"spatialReference" : {"wkid" : 54003},
'features':[{'geometry':{'x': -13308192.1956127,'y': 4221903.58555983}}]}
dist = {'distance':8.5,'units':'esriMiles'}
data = {'Input_Observation_Point': inPts,
'Viewshed_Distance': dist,
'f': 'pjson'}
taskUrl = "http://localhost:6080/arcgis/rest/services/WorldViewshed/GPServer/viewshed"
submitUrl = taskUrl + "/submitJob"
submitResponse = urllib.urlopen(submitUrl, urllib.urlencode(data))
submitJson = json.loads(submitResponse.read())
if 'jobId' in submitJson:
jobID = submitJson['jobId']
status = submitJson['jobStatus']
jobUrl = taskUrl + "/jobs/" + jobID
while status == "esriJobSubmitted" or status == "esriJobExecuting":
print "checking to see if job is completed..."
time.sleep(1)
jobResponse = urllib.urlopen(jobUrl, "f=json")
jobJson = json.loads(jobResponse.read())
if 'jobStatus' in jobJson:
status = jobJson['jobStatus']
if status == "esriJobSucceeded":
if 'results' in jobJson:
resultsUrl = jobUrl + "/results/"
resultsJson = jobJson['results']
for paramName in resultsJson.keys():
resultUrl = resultsUrl + paramName
resultResponse = urllib.urlopen(resultUrl, "f=json")
resultJson = json.loads(resultResponse.read())
print resultJson
if status == "esriJobFailed":
if 'messages' in jobJson:
print jobJson['messages']
else:
print "no jobId found in the response"
Python、ArcPy 和脚本工具入门
如果您不熟悉 Python、ArcPy 和脚本工具,下表列出的主题可以帮助您入门。
帮助主题 | 内容 |
---|---|
创建自己的地理处理工具的基本概念。 | |
Python 和 ArcPy 的介绍主题。这些主题中包含有关 Python 和 ArcPy 站点包的更详细主题。 | |
有关使用 Python 创建自定义脚本工具的介绍主题。 | |
熟悉脚本工具的创建过程后,通常需参阅本主题,本主题详细介绍了脚本工具参数的定义。 |