Tengo un conjunto de herramientas de Python en una caja de herramientas de Python (.pyt). Están divididas en múltiples archivos y módulos y han estado funcionando correctamente, pero ahora estoy viendo un comportamiento inconsistente en múltiples máquinas.
Básicamente, puedo ejecutar las herramientas desde el código, puedo importarlas y ejecutarlas desde el shell de Python en ArcMap, y puedo importar la caja de herramientas en ArcToolbox a través de ArcMap y ejecutarlas desde allí. Pero cuando navego a la caja de herramientas en ArcCatalog, cada una de las herramientas tiene una X roja y cuando hago clic derecho "¿Por qué?" me dice:
AttributeError: 'module' object has no attribute 'Parameter'
También me da el mismo error si abro el shell de Python en ArcCatalog y hago:
arcpy.ImportToolbox("C:/path/to/toolbox.tbx")
Aunque ese mismo comando, y la posterior invocación de la herramienta, funciona bien en la consola de ArcMap Python. Esto es en la primera línea que hace referencia a arcpy (esto es toolbox_utils.py).
import arcpy
def make_parameter(displayName, name, datatype, defaultValue=None,
parameterType='Optional', direction='Input'):
"""
This method prepopulates the paramaeterType
and direction parameters and leaves the setting a default value for the
newly created parameter as optional. The displayName, name and datatype are
the only required inputs.
"""
# create parameter with a few defaults
param = arcpy.Parameter(
displayName=displayName,
name=name,
datatype=datatype,
parameterType=parameterType,
direction=direction)
# set new parameter to a default value
param.value = defaultValue
# return the complete parameter object
return param
He probado a eliminar los archivos .pyc, a eliminar y restablecer los archivos de metadatos .xml y a reducir las herramientas al mínimo. Si pongo una herramienta vacía en una caja de herramientas genérica sin parámetros, funciona. Una vez que trato de romper en los módulos (que estaban trabajando muy bien), empiezo a recibir este error. Es como si ArcCatalog no está resolviendo la referencia arcpy.
EDITAR:
Sólo para que sea más confuso, si abro ArcMap, abro la ventana del Catálogo en ArcMap y busco exactamente la misma caja de herramientas, todas las herramientas funcionan. No hay X rojas. Inicié y detuve ambas aplicaciones - ArcCatalog me da el error, la ventana del Catálogo en ArcMap no lo hace.
Además, he comprobado que ArcMap y ArcCatalog utilizan la misma versión de Python y ambos apuntan a mi Python27 \ArcGIS10.3 directorio.
Proyecto de muestra
Si alguien quiere ver lo que he estado haciendo y ofrecer cualquier mejora, he puesto el proyecto de muestra del que he reducido mi Toolbox real en github. Si alguien quiere ayudarme a ampliarlo en una estructura de muestra realmente ajustada, sería genial. https://github.com/cmpalmer66/SamplePythonToolbox
Esta es mi estructura:
arcpy_utils
__init__.py
toolbox_utils.py
service
__init__.py
services.py
settings.py
test_services.py
toolpackages
__init__.py
service_one.py
service_two.py
toolbox.pyt
test_toolbox.py
*.xml
Toolbox.pyt parece:
import arcpy
from toolpackages.service_one import ServiceOne
from toolpackages.service_two import ServiceTwo
class Toolbox(object):
def __init__(self):
'''
Define the toolbox properties here. Do not change the name of this
class. ArcGIS locates this class by name. It will not be able to find
the toolbox and your toolbox will not work if you modify this.
'''
self.label = 'Toolbox'
self.alias = 'ABCD'
# List of tool classes associated with this toolbox
self.tools = [ServiceOne, ServiceTwo]
El directorio toolpackages contiene las definiciones de las herramientas, con el código real en el módulo de servicios.
He aquí un ejemplo de uno de los archivos de los paquetes de herramientas (sólo las primeras líneas):
import service.services as services_main
import arcpy_utils.toolbox_utils as utils
class ServiceOne(object):
"""
Does Service One
"""
def __init__(self):
"""
Define the tool class attributes, including your tool parameters.
"""
self.label = 'ServiceOne'
self.canRunInBackground = False
0 votos
¿Cómo estás importando toolbox_utils desde service_one (o cualquiera de los otros paquetes)? Con la estructura dada arriba, tu directorio de nivel superior no es un paquete y no puede ser usado con importaciones relativas. Estaba tratando de recrear la situación que tienes aquí, pero me encontré con eso.
0 votos
Oops, debería ser arcpy_utils, no toolbox_utils.
0 votos
Editado para añadir otro ejemplo de código
0 votos
Ah, vale, no estaba asumiendo que el directorio de nivel superior era el directorio de trabajo actual (que para ser justos, ArcGIS lo hace cuando se añade una caja de herramientas). Configuré una caja de herramientas simple, con su módulo arcpy_utils y un módulo de herramientas organizado en paquetes como usted tiene y funciona bien tanto en ArcGIS 10.2.1 como en ArcGIS Pro (así que Python 2.7 y 3.4). ¿Estás seguro de que no has redefinido arcpy en alguna parte por error? ¿Tienes cosas adicionales en tu paquete init?
0 votos
He decidido que ArcGIS es aparentemente muy frágil. He eliminado todas las herramientas menos una y ha funcionado. Sin NINGÚN otro cambio de código, descomenté las herramientas en toolbox.pyt y probé cada una de ellas hasta que todas fueron descomentadas y todas siguieron funcionando en ArcMap y ArcCatalog. Luego moví el mismo directorio de archivos a una máquina diferente y... tuve problemas similares pero diferentes. La misma versión. El mismo código.
0 votos
@CMPalmer. Un par de cosas para que pruebes. Cuando abras ArcCatalog, cierra cualquier ventana relacionada con el geoprocesamiento/Python (ventana de Python, historial de geoprocesamiento), cierra ArcCatalog y vuelve a abrir. Además (si usted está dispuesto a), borrar el historial de geoprocesamiento, y cerrar y volver a abrir ArcCatalog. ¿Esto libra a las herramientas del error de parámetro?
0 votos
En mi máquina 10.3, los servicios de ejemplo (en github) funcionan ahora sin hacer nada nuevo. En la 10.3.1, el mismo código sigue sin funcionar antes o después de los pasos sugeridos por @DWynne. Sigue diciendo que el módulo sample_one no se encuentra.