ArcPy条件表达式BUG(ERROR 000860)
已知一个DEM,需要用arcpy脚本将DEM中栅格值大于1000的部分设置为1,小于1000的部分设为0,我们自然想到用Con条件函数:
Con (in_conditional_raster, in_true_raster_or_constant, {in_false_raster_or_constant}, {where_clause})
参数 | 说明 | 数据类型 |
---|---|---|
in_conditional_raster | 表示所需条件结果为真或假的输入栅格。 可以是整型或浮点型。 | Raster Layer |
in_true_raster_or_constant | 条件为真时,其值作为输出像元值的输入。 可为整型或浮点型栅格,或为常数值。 | Raster Layer; Constant |
in_false_raster_or_constant (可选) | 条件为假时,其值作为输出像元值的输入。 可为整型或浮点型栅格,或为常数值。 | Raster Layer; Constant |
where_clause (可选) | 决定输入像元为真或假的逻辑表达式。 表达式遵循 SQL 表达式的一般格式。where_clause 的一个示例为 “VALUE > 100”。 | SQL Expression |
当我们新建一个.py脚本然后正常编写代码
# coding:cp936
import arcpy
# 布置环境
arcpy.env.workspace = r"E:\geo\Default.gdb"
arcpy.CheckOutExtension("spatial")
# 设置参数
dem=r"E:\geo\dem.tif"
save_file= r"E:\geo\结果.tif"
# 使用条件函数
# arcpy.gp.Con_sa(arcpy.sa.Raster(dem), 1, save_file, 0, "VALUE >= 1000") # 法一
result= Con(arcpy.sa.Raster(dem) > 1000, 1,0) # 法二
这时我们新建一个toolbox,添加一个脚本,绑定上一步的.py文件
接着运行可以正常得到结果:
讲道理我们就可以开心地打包程序即把.py文件导入
到脚本里,然后可以发给他人直接就能运行。可是事实是导入文件后再次执行就会在条件函数那一行报错:
File "e:\arcgis10.5\later\desktop10.5\arcpy\arcpy\geoprocessing\_base.py", line 510, in <lambda>
return lambda *args: val(*gp_fixargs(args, True))
ExecuteError: 执行失败。参数无效。
ERROR 000860: 输入条件为 true 时所取的栅格数据或常量值: 不是类型 复合地理数据集,或者不存在。
报错显示条件为true时参数无效,我们输入的是1,难道是导入后进过“暗箱操作”就识别不出int字符了? 可是API里明确指出参数可以是常数,这就犯迷糊了,于是打算用栅格计算器根据DEM生成一个全是0值的图层和全是1值的图层来代替0和1
zeros = Times(Raster(FlowAcc_Flow1),0)
ones = Plus(Raster(zeros),1)
显然参数里又包含了常数,果不其然又是报错了,这下可以确定就是数字搞得鬼,并且只在导入到程序后才有此问题。
就这样继续摸索发现arcpy.sa
模块下有许多逻辑运算符,其中> =
可以将第一个栅格数据大于或等于第二个栅格数据返回 1,否则返回 0
这不刚好避开前面的坑了吗,所以用> = 代替Con( )尝试:
result = Raster(dem)>=1000
最终得到一样的结果而且不报错!!!
总结:Arcgis10.5 下的Arcpy对字符支持有很多bug(严重怀疑和编码有关),条件函数或其它数学工具的表达式中能不用常数就不用常数,可以用逻辑运算符代替