เรียกใช้สคริปต์ Python (พร้อมพารามิเตอร์) ภายในสคริปต์ Python อื่นกับ ArcPy?


23

รูปแบบการเข้ารหัสทั่วไปที่ใช้ใน AML คือการเรียกใช้ AML (พร้อมพารามิเตอร์) ภายใน AML อื่น

แอปพลิเคชันที่ฉันกำลังพัฒนาอยู่ในขณะนี้จะได้รับประโยชน์จากความสามารถในการเรียกใช้สคริปต์ Python (พร้อมพารามิเตอร์) ภายในสคริปต์ Python อื่น

อย่างไรก็ตามสิ่งนี้ดูเหมือนจะไม่ตรงไปตรงมา

ใช้ ArcGIS 10 ฉันกำลังทดลองห่อสคริปต์ Python "inner" ลงในเครื่องมือ ArcGIS ที่มีพารามิเตอร์ ฉันคิดว่ามันเป็นเรื่องง่ายที่จะให้สคริปต์ Python "ด้านนอก" ใช้ arcpy.ImportToolbox เพื่อนำเข้ากล่องเครื่องมือแล้วเรียกใช้เครื่องมือที่อยู่ภายใน อย่างไรก็ตามในการทดสอบจนถึงทุกความพยายามของฉันเพื่อเรียกใช้เครื่องมือ "Inner" จากสคริปต์ "outer" ดูเหมือนว่าจะข้ามเครื่องมือ "inner" (ไม่มีข้อผิดพลาด)

นี่คือรหัสทดสอบบางส่วนที่จะลองและอธิบายให้ดีขึ้นว่าฉันพยายามอธิบายอะไร

สคริปต์ 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 เครื่องมือต้องใช้พารามิเตอร์สตริงเดียว

สำหรับ testouter.py เครื่องมือนั้นต้องการพารามิเตอร์ String สองตัว

เครื่องมือทั้งสองวางอยู่ใน test.tbx

test.gdb เพียงแค่ต้องการฟีเจอร์คลาสเดียวที่ว่างเปล่าที่เรียกว่าการทดสอบ

เมื่อคุณมีการประกอบด้านบนแล้วให้เรียกใช้เครื่องมือตัวทดสอบพร้อมกับสตริงเช่น 'abc' ที่ผ่านมาเนื่องจากพารามิเตอร์ควรส่งผลให้คลาส 'ทดสอบ' ถูกคัดลอกไปยังคุณลักษณะที่เรียกว่า 'abc' ตกลง

แต่เมื่อคุณลองเรียกใช้เครื่องมือ testouter ที่มีสองสตริงเช่น 'uvw' และ 'xyz' เป็นพารามิเตอร์เครื่องมือ testinner ใน testouter.py ดูเหมือนว่าจะทำงานตกลงหนึ่งครั้ง แต่ส่ง ArcMap 10 SP2 บน Vista SP2 ไปยัง Serious Application Error เมื่อ พยายามใช้มันเป็นครั้งที่สอง

การทดสอบเดียวกันโดยใช้ Windows XP SP3 และ ArcGIS Desktop 10 SP2 ยังสร้างข้อผิดพลาดร้ายแรงของแอปพลิเคชันในจุดเดียวกัน


2
ไปกับคำตอบของ @ Dan ในเรื่องนี้ ... อย่าคิดถึงไฟล์. py เช่นเดียวกับ "สคริปต์" คิดว่ามันเป็นโมดูลที่คุณสามารถนำมาใช้ใหม่และรีไซเคิลโดยการนำเข้าฟังก์ชั่นและคลาสที่คุณต้องการจากโมดูลเหล่านั้น สรุปพารามิเตอร์ GP ที่ซ้อนกันเหล่านั้นโดยใช้หนึ่งสคริปต์เพื่ออ่านในชุดพารามิเตอร์หนึ่งชุดจากนั้นเรียกใช้ฟังก์ชันในโมดูลอื่น ๆ ของคุณตามต้องการ ใช้เคล็ดลับif name __ == '__ main 'เพื่อทำให้โมดูลของคุณสามารถนำเข้าและแบบสแตนด์อโลนได้
blah238

ฉันมีตัวอย่างของ Dan ที่ทำงานเพื่อแสดงผล: C: \ Temp \ Main_program.py ('รวมบางตัวเลข:', 55) ('ผลรวมของกำลังสอง:', 385) ('สวัสดีจาก 8:', [1, 2, 3 , 4, 5, 6, 7, 8, 9, 10]) แต่ฉันพยายามที่จะปรับให้เข้ากับตัวอย่าง ArcPy เหมือนที่ฉันให้ไว้ข้างต้น ความช่วยเหลือเพิ่มเติมใด ๆ เกี่ยวกับสิ่งที่ตัวอย่างของ ArcPy จะได้รับการชื่นชมอย่างมาก
PolyGeo

ดูคำตอบที่ฉันเพิ่ม - ควรช่วยอธิบายสิ่งต่าง ๆ ในตัวอย่างของคุณให้ดีขึ้น
blah238

ฉันเพิ่งเจอโพสต์บล็อกที่ยอดเยี่ยมจาก Jason Pardy ที่ให้เทมเพลต 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)

ฉันคิดว่าคุณจะพบว่าวิธีการแยกส่วนนี้มีประสิทธิภาพมากขึ้นและสมเหตุสมผลเมื่อคุณคุ้นเคยกับมันแล้ว ส่วนโมดูลในมาตรฐานหลามกวดวิชายังเป็นทรัพยากรที่ดีสำหรับการทำความเข้าใจการทำงานของวิธีการนำเข้า

สำหรับตัวอย่างเฉพาะของ arcpy ดูที่สคริปต์ในตัวใน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 (สมมติว่าคุณกำลังใช้รุ่น 10 ของ arcmap) เพียงแค่ส่งการอ้างอิงไปยังมัน


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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.