Запуск сценаріїв Python (з параметрами) в іншому скрипті Python з ArcPy?


23

Загальний шаблон кодування, який використовується в AML, полягав у запуску AML (з параметрами) всередині іншого AML.

Додаток, який я зараз розробляю, виграє від можливості запуску сценарію Python (з параметрами) в іншому сценарії Python.

Однак це, здається, зовсім не прямо.

Використовуючи ArcGIS 10, я експериментую із загортанням «внутрішнього» сценарію Python в інструмент ArcGIS, у якого є параметри. Я думав, що було б простою справою "зовнішній" скрипт Python використовувати arcpy.ImportToolbox для імпорту інструментарію, а потім запустити інструменти (и) всередині нього. Однак у тестуванні поки що всі мої спроби запустити "внутрішній" інструмент із "зовнішнього" скрипту, здається, просто пропускають "внутрішній" інструмент (помилка не викидається).

Ось кілька тестових кодів, щоб спробувати проілюструвати краще те, що я намагаюся описати.

Мій скрипт testinner.py такий:

inputString = arcpy.GetParameterAsText(0)

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

Мій скрипт testouter.py:

import arcpy

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

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

arcpy.testinner_test(inputString1)

arcpy.testinner_test(inputString2)

Для testinner.py його інструменту потрібен єдиний параметр String.

Для testouter.py його інструменту потрібні два параметри String

Два інструменти розміщені у test.tbx.

Для test.gdb потрібен єдиний порожній клас функцій, який називається тестом.

Після того, як ви зібрали вищезгадане, запуск інструменту testinner із рядком типу "abc", переданим як його параметр, повинен призвести до того, що "тест" класу функцій буде скопійовано в один званий "abc" ОК.

Але коли ви намагаєтеся запустити інструмент testouter з двома рядками, такими як "uvw" та "xyz", як його параметри, інструмент testinner в межах testouter.py, здається, запуститься один раз в порядку, але посилає ArcMap 10 SP2 на Vista SP2 до серйозної помилки додатка, коли намагаються використати його вдруге.

Один і той же тест з використанням Windows XP SP3 та ArcGIS Desktop 10 SP2 також створює серйозну помилку програми в тій же точці.


2
Ідучи з відповіддю @ Дана на це… не думайте про .py файли як про «сценарії», вважайте їх модулями, які ви можете повторно використовувати та переробляти, імпортуючи потрібні функції та класи з цих модулів. Абстрагуйте ці вкладені параметри GP, використовуючи один скрипт, щоб прочитати в одному наборі параметрів, а потім зателефонуйте у інших модулях. Використовуйте трюк if name __ == '__ main ', щоб зробити ваші модулі одночасно важливими та доступними для самостійного використання.
blah238

У мене є приклад Дена, який працює на виведенні: C: \ Temp \ Main_program.py ('сума деяких чисел:', 55) ('сума квадратів:', 385) ('привіт від 8:', [1, 2, 3 , 4, 5, 6, 7, 8, 9, 10]), але я намагаюся адаптувати його до прикладу ArcPy, як я наводив вище. Будемо дуже вдячні за будь-яку подальшу допомогу щодо вигляду прикладу ArcPy.
PolyGeo

Дивіться відповідь, яку я додав - має допомогти пояснити речі в контексті вашого прикладу.
blah238

Я щойно натрапив на відмінну публікацію в блозі від Джейсона Парді, яка пропонує шаблон ArcPy, що містить шаблон кодування модулів Python на blogs.esri.com/Dev/blogs/geoprocessing/archive/2011/07/21/…
PolyGeo

це посилання з тих пір перемістилося, і я вважаю, що він зараз лежить тут: blogs.esri.com/esri/arcgis/2011/08/04/pythontemplate
ndimhypervol

Відповіді:


15

Ось ваш тестовий приклад, модифікований для імпорту модуля "утиліта" в основний сценарій та виклику функції за допомогою параметрів, прочитаних інструментом скрипту:


CopyFeaturesTool.py - інструмент сценарію, який читає параметри і викликає функцію в іншому модулі

import CopyFeaturesUtility
import arcpy

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

CopyFeaturesUtility.py - Модуль, який має єдину функцію copyFeaturesToTempGDB. Можна або імпортувати, або працювати окремо. Якщо запустити окремий код 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)

Я думаю, що ви зрозумієте, що цей модульний підхід буде набагато ефективнішим і логічнішим, коли ви звикли до нього. Розділ Модулі в стандартному навчальному посібнику Python також є хорошим ресурсом для розуміння того, як працює імпорт.

Для отримання додаткових прикладів, що стосуються архпій, подивіться на вбудовані сценарії у своїй C:\Program Files\ArcGIS\Desktop10.0\ArcToolbox\Scriptsпапці.


13

Ви можете досягти цього, імпортуючи модуль (тобто скрипт) у свій основний сценарій та викликаючи його функції. Простий демонстраційний вміст міститься в супровідних двох сценаріях.

    '''
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)

для основної програми та для функцій, які викликаються

'''
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

ви просто повинні забезпечити, щоб основний модуль і дочірній модуль знаходилися в одній папці. Ви можете легко передати параметри дочірньому модулю, і якщо дочірньому модулю потрібен доступ до arcpy (якщо ви користуєтеся версією Arcmap версії 10), просто передайте посилання на нього.


6

Імпорт та запуск функції - це більш чистий спосіб її виконати, але задля повноти є також execfileвбудована функція ( документація ), яка дозволить запустити довільний файл у поточному контексті.


0

Метод execfile, описаний @JasonScheirer, дозволив мені переставити свій код на той, що наведений нижче, і пропонує рішення моєї тестової проблеми:

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")

Однак це може виявитись громіздким, коли застосовуються до нетестових сценаріїв (ів), які набагато довші, тому я використав роботу @ blah238, яка схвалювала підхід @ DanPatterson і придумала наступний остаточний (тестовий) код, який робить саме те, що мені потрібно.

# 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)

і

# 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.