arcpy—服务发布
目录
1.引言
应公司需求,开发一个服务发布管理的功能模块。首先想到的是用AE的接口去实现,但是在开发的过程中或多或少的遇到了一些问题(在代码方面没有找到什么原因,也不确定是Arcgis 10.1的问题),最终迫于时间压力,并在ESRI客服的帮助下转向了Arcpy,这也是他们推荐的一种方式,下面的整篇将围绕服务发布展开。由于本人也是接触arcpy不久,若存在错误或者不合理的地方欢迎指正。
2.实现思路
- 创建arcpy脚本工具文件(*.pyt),使用arcpy实现服务发布功能。
- 在代码中将创建好的脚本工具文件加入到arcToolbox。
- 使用类似GP工具的调用方式调用已经创建的脚本工具来实现服务发布功能。
3.具体实现
(A).创建python脚本工具并用脚本实现功能
上面是创建结果,初始状态包含三个文件,其中*.pyt文件中是你实现服务发布的脚本代码所在,另外是两个xml配置文件(可删除),在脚本执行过程中还会生成一个中间的状态文件(可删除)。至于arcpy的脚本里面代码是什么意思,这里不会详细描述,具体可参考官方帮助,里面讲述的很详细,关于创建arcpy脚本工具箱及代码实现模块的详细说明。下面我直接贴出我的脚本代码:
class CreateService(object):
def __init__(self):
self.label = "CreateService"
self.description = "publish sevice"
self.canRunInBackground = False
def getParameterInfo(self):
# mxdPath:A string that represents the .mxd path.
mxdPath = arcpy.Parameter(
displayName="Mxd document path",
name="in_mxdPath",
datatype="DEFile",
parameterType="Required",
direction="Input")
# agsPath:A string that represents the .ags file path
agsPath = arcpy.Parameter(
displayName=".ags file path",
name="in_agsPath",
datatype="DEFile",
parameterType="Required",
direction="Input")
# serviceName:A string that represents the name of the service
serviceName = arcpy.Parameter(
displayName="service Name",
name="in_serviceName",
datatype="GPString",
parameterType="Required",
direction="Input")
# serviceDirectory:A string that represents the directory of the service
serviceDirectory = arcpy.Parameter(
displayName="service Directory",
name="in_serviceDirectory",
datatype="GPString",
parameterType="Optional",
direction="Input")
# summary:A string that represents the Item Description Summary.
summary = arcpy.Parameter(
displayName="summary",
name="in_summary",
datatype="GPString",
parameterType="Optional",
direction="Input")
# summary:A string that represents the Item Description Tags.
tags = arcpy.Parameter(
displayName="tags",
name="in_tags",
datatype="GPString",
parameterType="Optional",
direction="Input")
params = [mxdPath,agsPath,serviceName,serviceDirectory,summary,tags];
return params
def isLicensed(self):
"""Set whether tool is licensed to execute."""
return True
def updateParameters(self, parameters):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
return
def updateMessages(self, parameters):
"""Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation."""
return
def execute(self, parameters, messages):
mxdPath = parameters[0].valueAsText
agsPath = parameters[1].valueAsText
serviceName = parameters[2].valueAsText
serviceDirectory = parameters[3].valueAsText
summary = parameters[4].valueAsText
tags = parameters[5].valueAsText
new_mxd = arcpy.mapping.MapDocument(mxdPath)
sddraft = os.path.abspath(serviceName + '.sddraft')
sd = os.path.abspath(serviceName + '.sd')
if os.path.exists(sd):
os.remove(sd)
arcpy.CreateImageSDDraft(new_mxd, sddraft, serviceName, 'ARCGIS_SERVER', agsPath,False,serviceDirectory, summary, tags)
analysis = arcpy.mapping.AnalyzeForSD(sddraft)
if analysis['errors'] == {}:
arcpy.StageService_server(sddraft, sd)
arcpy.UploadServiceDefinition_server(sd, agsPath)
messages.addMessage("Service successfully published")
else:
messages.addErrorMessage("Service unsuccessfully published")
return agsPath.replace(".ags","/"+serviceName+".MapServer")
上述的实现可以参考官方的帮助文档
创建好的脚本在Arcmap或者ArcCatalog中可以打开并且执行:
(B).调用脚本
调用arcpy的脚本有很多种方式,比如说:cmd命令,比如说第三方动态链接库等等,由于是集成到了arcgis的环境中,所以我这里选择了arcgis的调用方式,下面贴出代码:
/// <summary>
/// 调用脚本工具箱
/// </summary>
/// <param name="pytPath">.pyt文件路径</param>
/// <param name="toolName">工具名称</param>
/// <param name="parameters">工具参数</param>
/// <param name="errorMsg">执行错误提示</param>
/// <returns>执行成功与否</returns>
public static PyGpOutMessage Execute(string pytPath, string toolName, IVariantArray parameters)
{
PyGpOutMessage outMsg = new PyGpOutMessage();
if (string.IsNullOrEmpty(toolName) || parameters == null || parameters.Count <= 0)
{
outMsg.ErrorMessage = "空参数异常,请检查传入参数是否有问题!";
outMsg.IsSucced = false;
return outMsg;
}
try
{
Geoprocessor gp = new Geoprocessor();
if (!File.Exists(pytPath))
{
outMsg.ErrorMessage = "python 脚本工具箱文件不存在,请检查后再使用!";
outMsg.IsSucced = false;
return outMsg;
}
gp.AddToolbox(pytPath);
IGeoProcessorResult results = (IGeoProcessorResult)gp.Execute(toolName, parameters, null);
if (results != null && results.Status == esriJobStatus.esriJobSucceeded)
{
outMsg.ErrorMessage = string.Empty;
outMsg.IsSucced = true;
outMsg.Returns = results.ReturnValue;
return outMsg;
}
else
{
outMsg.ErrorMessage = "脚本执行失败:请检查工具参数是否正确以及ARCGIS许可绑定等相关内容!";
outMsg.IsSucced = false;
return outMsg;
}
}
catch(Exception ex)
{
outMsg.ErrorMessage = string.Format("错误提示:{0}\r\n请检查工具参数是否正确以及ARCGIS许可绑定等相关内容!", ex);
outMsg.IsSucced = false;
return outMsg;
}
}
代码说明:
- PyGpOutMessage—自定义输出对象,可以不予理睬。
- gp.AddToolbox(pytPath);该行代码将脚本加入到ToolBox工具箱中。
4.踩过的坑
坑A:python的严格缩进所造成的工具箱无法运行(具体表现为ArcCatalog或ArcMap中所创建的脚本工具前面出现红色的“×”,双击在ArcMap中报错),这个问题的关键在于Pyhton语言的严格缩进,详细信息可以百度,很多说明,这里不画蛇添足。
坑B:我使用的是ArcGIS10.1环境,由于 arcpy是在10.1版本开始集成进去的,运行机制还不是很稳定,造成的一个问题就是我怎么折腾工具脚本都出问题,最后才发现需要安装ArcGIS10.1的SP1补丁包(差点就死在坑里了),后续的10.2,10.3,10.4,10.5应该会好些(注:我没有测试过)。
坑C:脚本的运行需要依赖高级许可,造成的问题是你使用ArcMap直接运行脚本界面没有任何问题,服务发布结果也是对的,但是只要在代码中调用脚本(ArcEngine)就报错,感觉莫名奇妙,最后在ESRI客服的帮助下才发现问题所在:绑定许可的时候绑定EngineOrDesktop,在安装了AE的情况下默认会使用AE的许可,而AE不是高级许可,所以一调用就出错,也就是说许可应该直接绑定到Desktop。
现在回头想来功能开发并不是很难,只是这些坑对于我这样一个没有很多经验的工程师来说确实有点残忍,将这些坑点列出来与大家分享一下,真心希望少走弯路。基于的arcpy的服务发布功能就介绍到这里,篇中错误及不合理,欢迎指正,相互学习。
5.参考文章及帮助
①.利用Arcpy发布地图服务以及制作切片
②从地图文档 (MXD) 发布地图服务
③Arcpy官方教程
转载自:https://blog.csdn.net/wucdsg/article/details/77100370