¿Ejecutar scripts de Python (con parámetros) dentro de otro script de Python con ArcPy?

23

Un patrón de codificación común utilizado en la AML era ejecutar una AML (con parámetros) dentro de otra AML.

Una aplicación que estoy desarrollando actualmente se beneficiaría de poder ejecutar un script de Python (con parámetros) dentro de otro script de Python.

Sin embargo, esto no parece ser en absoluto sencillo.

Al usar ArcGIS 10, estoy experimentando con envolver el script Python "interno" en una herramienta de ArcGIS que tiene los parámetros. Pensé que sería una cuestión simple que el script Python "externo" usara arcpy.ImportToolbox para importar la caja de herramientas y luego ejecutar las herramientas dentro de ella. Sin embargo, al probar hasta ahora, todos mis intentos de ejecutar la herramienta "interna" desde el script "externo" parecen simplemente omitir la herramienta "interna" (no se produce ningún error).

Aquí hay un código de prueba para intentar ilustrar mejor lo que estoy tratando de describir.

Mi script testinner.py es:

inputString = arcpy.GetParameterAsText(0)

newFC = "C:\Temp\test.gdb\" + inputString
arcpy.Copy_management("C:\Temp\test.gdb\test",newFC)

Mi script testouter.py es:

import arcpy

inputString1 = arcpy.GetParameterAsText(0)
inputString2 = arcpy.GetParameterAsText(1)

arcpy.ImportToolbox("C:\Temp\test.tbx")

arcpy.testinner_test(inputString1)

arcpy.testinner_test(inputString2)

Para testinner.py, su herramienta necesita un único parámetro String.

Para testouter.py su herramienta necesita dos parámetros de cadena

Las dos herramientas se colocan en un test.tbx.

El test.gdb solo necesita una única clase de entidad vacía llamada prueba.

Una vez que haya ensamblado lo anterior, ejecute la herramienta testinner con una cadena como 'abc', ya que su parámetro debería hacer que la clase de entidad 'prueba' se copie a una llamada 'abc' OK.

Pero cuando intentas ejecutar la herramienta testouter con dos cadenas como 'uvw' y 'xyz' como sus parámetros, la herramienta testinner en testouter.py parece funcionar bien una vez, pero envía ArcMap 10 SP2 en Vista SP2 a un serio Error de aplicación al intentar usarlo por segunda vez.

La misma prueba que usa Windows XP SP3 y ArcGIS Desktop 10 SP2 también produce un error de aplicación grave en el mismo punto.

    
pregunta PolyGeo 22.06.2011 - 09:03

4 respuestas

15

Aquí se modifica su ejemplo de prueba para importar un módulo de "utilidad" dentro del script principal y llamar a una función utilizando los parámetros leídos por la herramienta de script:

CopyFeaturesTool.py : herramienta de script que lee parámetros y llama a una función en otro módulo

import CopyFeaturesUtility
import arcpy

inputFC = arcpy.GetParameterAsText(0)
outputFCName = arcpy.GetParameterAsText(1)
CopyFeaturesUtility.copyFeaturesToTempGDB(inputFC, outputFCName)

CopyFeaturesUtility.py : módulo que tiene una función única copyFeaturesToTempGDB . Se puede importar o ejecutar de forma independiente. Si se ejecuta de forma independiente, se ejecuta el código debajo de if __name__ == '__main__' .

import arcpy
import os

def copyFeaturesToTempGDB(inputFeatures, outputName):
    """Copies the input features to a temporary file geodatabase.
    inputFeatures: The input feature class or layer.
    outputName: The name to give the output feature class."""

    tempGDB = r"c:\temp\test.gdb"
    newFC = os.path.join(tempGDB, outputName)
    arcpy.env.overwriteOutput = True
    arcpy.CopyFeatures_management(inputFeatures, newFC)

if __name__ == '__main__':
    inputFC = r"c:\temp\test.gdb\test"
    outputFCName = "testCopy"
    copyFeaturesToTempGDB(inputFC, outputFCName)

Creo que encontrarás que este enfoque modular es mucho más eficiente y lógico una vez que te hayas acostumbrado. La sección de módulos en el tutorial estándar de Python también es un buen recurso para entender cómo funciona la importación .

Para ver ejemplos más específicos de arcpy, eche un vistazo a los scripts incorporados en su carpeta C:\Program Files\ArcGIS\Desktop10.0\ArcToolbox\Scripts .

    
respondido por el blah238 23.06.2011 - 19:32
13

Puede lograr esto importando un módulo (es decir, un script) a su script principal y llamando a sus funciones. Una simple demostración está contenida en los dos scripts que se acompañan.

    '''
Main_program.py

demonstrates how to import and call functions from another module
'''
import sys
import CallingFunctions

a_list = [1,2,3,4,5,6,7,8,9,10]
print sys.argv[0]
print CallingFunctions.func1(a_list)
print CallingFunctions.func5(a_list)
print CallingFunctions.func8(a_list)

para el programa principal y para las funciones que se están llamando

'''
Callingfunctions.py

imported into another program giving it access to the functions
'''

def func1(inputs=None):
  x = sum(inputs)
  return "sum some numbers: ", x
'''
more functions
'''
def func5(inputs=None):
  x_sq = 0
  for x in inputs:
    x_sq += x**2
  return "sum of squares: ", x_sq
'''
more functions
'''
def func8(inputs=None):
  return "hello from 8: ", inputs

'''
more functions
'''
if __name__ == "__main__":
  a_list = [1,2,3,4,5,6,7,8,9,10]
  inputs = "test inputs"
  a_dict = {1:[func1([1,2,3]) ],
            5:[func5([1,2,3])],
            8:[func8("inputs to 8")]}
  needed = [1,5,8]
  for akey in needed:
    if akey in a_list:
      action = a_dict[akey]
      print "\naction: ", action

solo tiene que asegurarse de que el módulo principal y el módulo secundario estén en la misma carpeta. Puede pasar los parámetros al módulo secundario fácilmente y si el módulo secundario necesita acceso a arcpy (suponiendo que esté utilizando la versión 10 de arcmap), simplemente pase una referencia al mismo.

    
respondido por el user681 22.06.2011 - 13:02
6

Importar y ejecutar una función es la forma más limpia de hacerlo, pero para completar, también existe la función incorporada execfile ( documentación ) que le permitirá ejecutar un archivo arbitrario en el contexto actual.

    
respondido por el Jason Scheirer 22.06.2011 - 18:11
0

El método execfile descrito por @JasonScheirer me permitió reorganizar mi código a continuación y ofrece una solución para mi problema de prueba:

import arcpy

inputString1 = arcpy.GetParameterAsText(0)
inputString2 = arcpy.GetParameterAsText(1)

arcpy.ImportToolbox("H:/Temp/test.tbx")

# Write second Python script to an ASCII file for first parameter & execute it
f = open("H:/Temp/string1.py","w")
f.write('newFC = "H:/Temp/test.gdb/' + inputString1 + '"' + "\n")
f.write('arcpy.Copy_management("H:/Temp/test.gdb/test"' + ',newFC)')
f.close()
execfile("H:/Temp/string1.py")

# Write third Python script to an ASCII file for second parameter & execute it
f = open("H:/Temp/string2.py","w")
f.write('newFC = "H:/Temp/test.gdb/' + inputString2 + '"' + "\n")
f.write('arcpy.Copy_management("H:/Temp/test.gdb/test"' + ',newFC)')
f.close()
execfile("H:/Temp/string2.py")

Sin embargo, esto puede resultar engorroso cuando se aplica a scripts que no son de prueba, que son mucho más largos, así que usé @ blah238's trabajo que respaldó el el enfoque de @PanDPatterson y creó el siguiente código final (de prueba) que hace exactamente lo que necesito.

# CopyFeaturesTool.py

import CopyFeaturesUtility
import arcpy
outputFCName = arcpy.GetParameterAsText(0)
outputFCName2 = arcpy.GetParameterAsText(1)

CopyFeaturesUtility.copyFeaturesToTempGDB("C:\Temp\test.gdb\test", outputFCName)
CopyFeaturesUtility.copyFeaturesToTempGDB("C:\Temp\test.gdb\test", outputFCName2)

y

# CopyFeaturesUtility.py

import arcpy
import os

def copyFeaturesToTempGDB(inputFeatures, outputName):
    """Copies the input features to a temporary file geodatabase.
    inputFeatures: The input feature class or layer.
    outputName: The name to give the output feature class."""

    tempGDB = r"C:\Temp\test.gdb"
    newFC = os.path.join(tempGDB, outputName)
    arcpy.env.overwriteOutput = True
    arcpy.Copy_management(inputFeatures, newFC)

if __name__ == '__main__':
    inputFC = r"C:\Temp\test.gdb\test"
    outputFCName = arcpy.GetParameterAsText(0)
    copyFeaturesToTempGDB(inputFC, outputFCName)
    
respondido por el PolyGeo 18.04.2016 - 00:08

Lea otras preguntas en las etiquetas