6 votos

¿Comprensión de la sintaxis para CalculateField_management en ArcPy?

Necesito utilizar CalculateField_management en un script de Python, y la expresión calc necesita concatenar una variable de tiempo de ejecución, una cadena y un valor de campo (cadena). He buscado por todas partes ejemplos de los que aprender. He intentado muchas cosas que he encontrado en mi investigación y algunas de mis propias ideas, también, pero no puedo conseguir la expresión calc para evaluar. Ahora estoy completamente confundido y necesito un poco de ayuda para salir de este agujero. Así que, aquí está la primicia.

El campo a calcular, DESCRIP, es un campo de cadena en una clase de característica fGDB con una característica. La variable de tiempo de ejecución, enddesg será una cadena. Básicamente, lo que quiero hacer es concatenar el valor de tiempo de ejecución con una cadena (larga) y añadirla al valor existente en el campo DESCRIP, almacenando el resultado de nuevo en el campo DESCRIP. He probado muchas formas de una cadena "todo en uno" para la expresión, pero nada funcionó. Llegué a la conclusión de que un enfoque pre-lógica sería mejor, pero no he sido capaz de conseguir que funcione tampoco. A continuación es lo que tengo en este momento.

expr = "getDescription(str(enddesg))"
codeblock = """def getDescription(endstr):
    exprstr = endstr + ' Touchdown Zone Elevation;duplicated from existing control point;' + !DESCRIP!
    return exprstr"""
arcpy.CalculateField_management(perpptsSX_src, "DESCRIP", expr, 'PYTHON_9.3', codeblock)  #Should be only one feature in the source

(Por cierto, el enddesg es una cadena o un entero, pero se convierte a una cadena como entrada). Obtengo el siguiente error

<class 'arcgisscripting.ExecuteError'>: Failed to execute. Parameters are not valid.
ERROR 000989: Python syntax error: Parsing error <type 'exceptions.SyntaxError'>: invalid syntax (line 2)

Failed to execute (CalculateField).

La siguiente variación de código no produce errores, pero tampoco consigo introducir nada en el campo DESCRIP.

expr = "getDescription(str(enddesg), !DESCRIP!)"
codeblock = """def getDescription(endstr, desc):
    exprstr = endstr + ' Touchdown Zone Elevation;duplicated from existing control point;' + desc
    return exprstr"""

Ahora estoy completamente confundido.

10voto

auramo Puntos 161

Nunca entiendo por qué la gente intenta meterse con CalculateField_management dentro de un script de Python en lugar de hacer sus actualizaciones dentro de un UpdateCursor .

No sólo no tiene que preocuparse de escapar caracteres y escribir funciones Python dentro de cadenas Python (escalofrío), sino que puede actualizar varios campos a la vez.

Es muy fácil con la nueva sintaxis de iteración del cursor de arcpy:

rows = arcpy.UpdateCursor(fc)
for row in rows:
    row.DESCRIP = "%s Touchdown Zone Elevation;duplicated from existing control point;%s" % (str(enddesg), row.DESCRIP)
    rows.updateRow(row)
del rows

La magia del row.DESCRIP = línea se llama formato de cadena en Python -- en este caso no era tan necesario pero cuando estás concatenando más de un par de cadenas o necesitas algún formato numérico específico es realmente útil.

Otra cosa que hay que tener en cuenta es que en lugar de codificar el nombre del campo ( row.DESCRIP ) también puede obtener y establecer valores de campo utilizando una variable para especificar el campo utilizando row.getValue y row.setValue en su lugar.

En la mayoría de los casos, sugeriría utilizar getValue y setValue ya que hace que su código sea mucho más fácil de mantener si el nombre del campo cambia o si desea escribir una función genérica o una herramienta de script con el nombre del campo(s) como parámetros.

0 votos

Gracias por esto. Normalmente evito Update Cursors, porque el rendimiento puede ser abismal en grandes conjuntos de datos. Normalmente trabajo con conjuntos de datos muy grandes y no me di cuenta de que, en este caso, la velocidad no es un problema. El método del cursor de actualización funcionó bien, por supuesto, y seguiré adelante. Sólo para mi propia edificación, sin embargo, realmente me gustaría encontrar la solución a la utilización de CalculateField. Trabajo con complejos scripts heredados que necesitan actualizarse de vez en cuando. El conocimiento sería útil. Gracias de nuevo a todos.

0 votos

Los cursores son lentos y malolientes :( Y además, puedes usar la sustitución de cadenas con la misma facilidad en un bloque de código, ¿no?

1 votos

@Nathanus, nunca he notado problemas de rendimiento con UpdateCursors pero en 10.1 se supone que son más rápidos. Me interesaría ver si alguien ha cronometrado los dos con tablas de distinto tamaño. Y claro que se puede hacer la sustitución de cadenas en una función escrita en el bloque de código de CalculateValue, pero me parece que hacerlo es menos fácil de mantener y de leer y en general un engorro comparado con hacerlo con un cursor. Usted tendría que hacer CalculateValue una vez para cada campo que seguramente va a ser más lento que un cursor que actualiza varios campos a la vez.

3voto

user2013 Puntos 2301

Puede que me equivoque, pero creo que no se debe poner el nombre del campo !DESCRIP! en el bloque de código. Utilice una variable de marcador de posición y debería funcionar correctamente.

1 votos

Sí. !field! sólo funciona en la expresión.

2voto

Daniel Broekman Puntos 1951

En mis pruebas, llamar a str() en un argumento de su expresión hace que la herramienta falle. Tal vez lo intente:

expr = "getDescription(enddesg, !DESCRIP!)"
codeblock = """def getDescription(endstr, desc):
    exprstr = str(endstr) + ' Touchdown Zone Elevation;duplicated from existing control point;' + desc
    return exprstr"""

0 votos

¿Por qué no convertirlo en una cadena dentro del bloque de código para que pueda concatenar felizmente?

0 votos

@Nathanus eso debería funcionar :-), voy a editar mi respuesta.

0 votos

@Derek Swingley - Yo también pensé que funcionaría... hasta que no lo hizo. Mismo resultado. No hay errores, sólo nada entró en el campo DESCRIP. Traté de convertir el enddesg a una cadena antes de la sentencia de expresión y simplemente pasar la cadena: sin convertir ni en la sentencia de expresión ni en el bloque de código. El resultado sigue siendo el mismo. Hmmm. Seguiré dándole vueltas a esto, pero agradecería cualquier otra idea que tengáis.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X