在 Python 脚本中的用法

可以编写 Python 脚本,以多种方式运行并使用 web 工具或地理处理服务。 运行脚本的主要方法是使用 ArcPyArcPy 内置用于连接、运行和处理服务结果的方法。 此外,要从 ArcGIS REST API 访问该服务,可以通过内置的 Python 模块调用使用 JSON 结构的 REST,以便传输结果。 您将必须使用 Python 代码在临时工作空间构建客户端以便使用 ArcPy。 大多数脚本均通过 ArcPy 来连接和使用地理处理服务。

注:

以下示例将使用联合 ArcGIS Server 上的地理处理服务。 在 Python 中,您永远不会使用门户中的相应 web 工具项目。

使用 ArcPy

ArcGIS Pro 中,可以通过 Python 窗口(脚本工具或独立的脚本)来访问 web 工具。 ImportToolbox 函数通过服务 URL 和其他值以连接并使用 Web 工具。

示例:将 ImportToolbox 与 SOAP URL、文件夹中的服务以及用户名和密码配合使用以连接到服务。


arcpy.ImportToolbox("https://organization.example.com/<context>/services;GPFolder/BufferService;serverusername;serverpassword")

Web 工具或地理处理服务既可以同步运行,也可以异步运行。 作为 Python 脚本作者,您必须了解如何运行服务,才能使用该服务。 IsSynchronous 属性用于确定服务是同步运行,还是异步运行。 当服务同步运行时,将自动返回结果,但在服务完成之前,将无法执行任何操作。 当服务异步运行时,必须定期查询当前状态。 当服务完成后,即可访问结果。

下列 Python 代码显示了如何连接到异步地理处理服务。 该代码将使用 ArcPy 函数来运行服务、获取结果以及进一步处理服务。 通过在运行任务时设置结果变量,可使用 while 循环检查 Result 对象的状态。 返回状态码 4 (成功)或更高状态码时,表示任务完成。

使用异步服务创建缓冲区并在本地保存结果。

import arcpy
import time

arcpy.ImportToolbox("https://organization.example.com/<context>/services;Elevation/viewshedAlias;serverusername;serverpassword")

result = arcpy.viewshedAlias.Viewshed(r'c:\data.gdb\inputPoint', "10000 Kilometers")

while result.status < 4:
	   print(result.status)
	   time.sleep(0.2)
print("Tool finished")

print(result.getMessages())
arcpy.management.CopyFeatures(result, r'c:\results.gdb\result')

了解有关使用 Python 中工具的详细信息。

使用 REST 端点

使用 web 工具的另一种方法是通过编写用于使用 JSON 作为数据交换格式执行 REST 调用的脚本。 此方法需要编写代码以发送请求和处理响应。

发送和接收 REST 消息更加复杂,因为您必须处理输入和输出语法的所有方面。 当发送和接收 REST 消息时,这些消息能够以一致方式返回。 请求可以通过 HTTP GETHTTP POST 方法发送,而响应则以 JSON 结构返回。

以下示例演示了如何发送请求和处理响应。

发送请求

例如,可以从 https://organization.example.com/<context>/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 浏览器地址栏中使用。

https://organization.example.com/<context>/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 模块 urlliburllib2 提交 URL。 以下 Python 代码将以使用服务目录或者将链接复制到 web 浏览器地址栏的类似方法来运行上述请求:


import urllib.request as urlopen
import urllib.parse as urlencode
import urllib.request as request
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 = 'https://organization.example.com/<context>/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed/execute'

req = request.Request(URL, urlencode.urlencode(data).encode('UTF-8'))
response = urlopen.urlopen(req)
response_bytes = response.read()
print(json.loads(response_bytes.decode('UTF-8')))

Result 对象将以字符串格式返回。 可以使用多种方法来生成请求和解析结果;上例仅是其中一种方法。 可以使用 json.loads() 将 web 工具返回的 JSON 放入字典中。 根据 web 工具的输出,这可能是最佳方法,否则,在 Python 中通过 REST 使用 web 工具时,可能需要浏览其他选项来处理输出。

注:

在使用结果要素时,请确保使用实际 x,y 对对工作流有意义,因为您不会通过 ArcPy 以支持几何的格式接收实际要素。

异步运行的服务要求定期检查任务的状态,以便查看任务是否完成,这与以上使用 ArcPy 的示例类似。 Python 代码可以在检查作业状态时返回的 jobStatus 状态消息中查找 esriJobSucceededesriJobFailed 短语。 下列代码示例演示使用异步 web 工具(使用 submitJob)的一种方法。

import urllib.request as urlopen
import urllib.parse as urlencode
import urllib.request as request
import json
import time


def sendReq(URL, data=None):

    req = request.Request(URL, urlencode.urlencode(data).encode('UTF-8'))
    response = urlopen.urlopen(req)
    response_bytes = response.read()
    return json.loads(response_bytes.decode('UTF-8'))


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 = "https://organization.example.com/<context>/rest/services/Elevation/GPServer/viewshed"
submitUrl = taskUrl + "/submitJob"

submitJson = sendReq(submitUrl, data)

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)

        jobJson = sendReq(jobUrl, {"f": "json"})

        if 'jobStatus' in jobJson.keys():
            status = jobJson['jobStatus']

            if status == "esriJobSucceeded":
                if 'results' in jobJson:
                    resultsJson = jobJson['results']
                    for paramName in resultsJson.keys():
                        resultsUrl = jobUrl + "/" + resultsJson[paramName]['paramUrl']
                        resultJson = sendReq(resultsUrl, {"f": "json"})
                        print(resultJson)

            if status == "esriJobFailed":
                if 'messages' in jobJson.keys():
                    print(jobJson['messages'])

else:
    print("No jobId found in the response")

相关主题