ArcGIS Pro tells me there is a syntax error when I run the single tool in this toolbox. Contrary to what the doc page for ERROR 00989 says it does not report what or where the error is. I can't find it visually and `python -m compileall ImageRepo.pyt` says it's fine. Can any of you see what is wrong?
I'm using ArcGIS Pro v2.8.1.
The toolbox: https://gist.github.com/maphew/0bae6f3005ca129f2a9566e343cf37d7
GdalToCog
=====================
Parameters
Input Raster Finlayson124_SP6_13Sep2017_150cm_pro_nd.tif
Output Raster D:\work\ImgRepo\2021-06-10\pro_pyt_to_cog.tif
=====================
Messages
ERROR 000989: Python syntax error: within script T:\ENV.558\ImageRepo.pyt
Solved! Go to Solution.
It is working fine for me in Pro 2.8.1 when I specify an input tif file stored on disk. I can make it error when choosing a tif file from my map, however the error is different (No such file or directory). I think GDAL cannot resolve the path when running it this way. In your parameters, the input file doesn't have a path - maybe try passing it the full path and filename. Does it error on other input files?
The other option is that something messed up when creating your local copy of the script or maybe some issue with your Python environment? Are you using the default environment?
This works:
# -*- coding: utf-8 -*-
import arcpy
from osgeo import gdal
gdal.UseExceptions()
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Toolbox"
self.alias = "toolbox"
# List of tool classes associated with this toolbox
self.tools = [Tool]
class Tool(object):
def __init__(self):
"""Gdal to Cloud Geotiff translator."""
self.label = "GdalToCog"
self.description = "Compress a raster to Cloud Optimized Geotiff, using the options that work best for our imagery at Environment Yukon"
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
params = []
params += [arcpy.Parameter(
displayName = "Input Raster",
name = "in_raster",
datatype="GPRasterLayer",
parameterType="Required",
direction="Input"
)]
params += [arcpy.Parameter(
displayName="Output Raster",
name="out_raster",
datatype="DERasterDataset",
parameterType="Required",
direction="Output"
)]
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):
"""Source code (adapted from 'gdal-to-cog.py')"""
infile = parameters[0].valueAsText
outfile = parameters[1].valueAsText
gdal.SetConfigOption('GDAL_CACHEMAX','30%')
options = ["COMPRESS=ZSTD", "PREDICTOR=YES", "LEVEL=17", "BIGTIFF=YES",
"NUM_THREADS=ALL_CPUS",]
def progress_cb(complete, message, cb_data):
'''Emit progress report in numbers for 10% intervals and dots for 3%'''
if int(complete*100) % 10 == 0:
print(f'{complete*100:.0f}', end='', flush=True)
elif int(complete*100) % 3 == 0:
print(f'{cb_data}', end='', flush=True)
arcpy.AddMessage(f'Translating {infile} to {outfile}')
gdal.Translate(outfile, infile, creationOptions=options,
format="COG",
callback=progress_cb,
callback_data='.'
)
return
It is working fine for me in Pro 2.8.1 when I specify an input tif file stored on disk. I can make it error when choosing a tif file from my map, however the error is different (No such file or directory). I think GDAL cannot resolve the path when running it this way. In your parameters, the input file doesn't have a path - maybe try passing it the full path and filename. Does it error on other input files?
The other option is that something messed up when creating your local copy of the script or maybe some issue with your Python environment? Are you using the default environment?
This works:
# -*- coding: utf-8 -*-
import arcpy
from osgeo import gdal
gdal.UseExceptions()
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Toolbox"
self.alias = "toolbox"
# List of tool classes associated with this toolbox
self.tools = [Tool]
class Tool(object):
def __init__(self):
"""Gdal to Cloud Geotiff translator."""
self.label = "GdalToCog"
self.description = "Compress a raster to Cloud Optimized Geotiff, using the options that work best for our imagery at Environment Yukon"
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
params = []
params += [arcpy.Parameter(
displayName = "Input Raster",
name = "in_raster",
datatype="GPRasterLayer",
parameterType="Required",
direction="Input"
)]
params += [arcpy.Parameter(
displayName="Output Raster",
name="out_raster",
datatype="DERasterDataset",
parameterType="Required",
direction="Output"
)]
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):
"""Source code (adapted from 'gdal-to-cog.py')"""
infile = parameters[0].valueAsText
outfile = parameters[1].valueAsText
gdal.SetConfigOption('GDAL_CACHEMAX','30%')
options = ["COMPRESS=ZSTD", "PREDICTOR=YES", "LEVEL=17", "BIGTIFF=YES",
"NUM_THREADS=ALL_CPUS",]
def progress_cb(complete, message, cb_data):
'''Emit progress report in numbers for 10% intervals and dots for 3%'''
if int(complete*100) % 10 == 0:
print(f'{complete*100:.0f}', end='', flush=True)
elif int(complete*100) % 3 == 0:
print(f'{cb_data}', end='', flush=True)
arcpy.AddMessage(f'Translating {infile} to {outfile}')
gdal.Translate(outfile, infile, creationOptions=options,
format="COG",
callback=progress_cb,
callback_data='.'
)
return
Interesting. On my machine I needed to a) use a full path and not a map layer, and b) disable the `callback` options. I tried with both default Pro python and a clone env (created using File >> Python >> Manage).
I think there might be something screwy with my install though, because a test python toolbox with nothing in it but the demo Set Progressor takes over 4 minutes to run, but the actual tool execution part is only 18 seconds.