Menjalankan skrip Python (dengan parameter) di dalam skrip Python lain dengan ArcPy?

23

Pola pengkodean yang umum digunakan dalam AML adalah menjalankan AML (dengan parameter) di dalam AML lain.

Aplikasi yang saat ini saya kembangkan akan mendapat manfaat karena dapat menjalankan skrip Python (dengan parameter) dalam skrip Python lain.

Namun, ini tampaknya tidak langsung sama sekali.

Menggunakan ArcGIS 10, saya bereksperimen dengan membungkus skrip Python "dalam" ke dalam alat ArcGIS yang memiliki parameter. Saya pikir ini akan menjadi masalah sederhana untuk memiliki skrip Python "luar" menggunakan arcpy.ImportToolbox untuk mengimpor kotak alat dan kemudian menjalankan alat di dalamnya. Namun, dalam pengujian sejauh ini semua upaya saya untuk menjalankan alat "dalam" dari skrip "luar" tampaknya hanya melewatkan alat "dalam" (tidak ada kesalahan dilemparkan).

Berikut adalah beberapa kode uji untuk mencoba dan menggambarkan dengan lebih baik apa yang saya coba gambarkan.

Skrip testinner.py saya adalah:

inputString = arcpy.GetParameterAsText(0)

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

Skrip testouter.py saya adalah:

import arcpy

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

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

arcpy.testinner_test(inputString1)

arcpy.testinner_test(inputString2)

Untuk testinner.py alatnya membutuhkan parameter String tunggal.

Untuk testouter.py alatnya membutuhkan dua parameter String

Dua alat ditempatkan di test.tbx.

Test.gdb hanya membutuhkan satu kelas fitur kosong bernama test.

Setelah Anda memiliki yang dirakit di atas, menjalankan alat testinner dengan string seperti 'abc' dilewatkan sebagai parameternya akan menghasilkan 'tes' kelas fitur yang disalin ke yang disebut 'abc' OK.

Tetapi ketika Anda mencoba menjalankan alat testouter dengan dua string seperti 'uvw' dan 'xyz' sebagai parameternya, alat testinner dalam testouter.py tampaknya berjalan OK sekali, tetapi mengirimkan ArcMap 10 SP2 pada Vista SP2 ke Serious Application Error saat mencoba menggunakannya kedua kalinya.

Pengujian yang sama menggunakan Windows XP SP3 dan ArcGIS Desktop 10 SP2 juga menghasilkan Kesalahan Aplikasi Serius pada titik yang sama.

PolyGeo
sumber
2
Pergi dengan jawaban @ Dan tentang ini ... jangan menganggap file .py hanya sebagai "skrip", anggap mereka sebagai modul yang dapat Anda gunakan kembali dan daur ulang dengan mengimpor fungsi dan kelas yang Anda butuhkan dari modul-modul itu. Abaikan parameter GP bersarang dengan menggunakan satu skrip untuk membaca dalam satu set parameter dan kemudian panggil fungsi dalam modul Anda yang lain sesuai kebutuhan. Gunakan trik if name __ == '__ main ' untuk membuat modul Anda berdua dapat diimpor dan masih bisa digunakan sendiri.
blah238
Saya memiliki contoh Dan yang berfungsi untuk menghasilkan: C: \ Temp \ Main_program.py ('jumlah beberapa angka:', 55) ('jumlah kotak:', 385) ('halo dari 8:', [1, 2, 3 , 4, 5, 6, 7, 8, 9, 10]) tetapi saya berjuang untuk menyesuaikannya dengan contoh ArcPy seperti yang saya berikan di atas. Bantuan lebih lanjut tentang seperti apa contoh ArcPy akan sangat dihargai.
PolyGeo
Lihat jawaban yang saya tambahkan - seharusnya membantu menjelaskan hal-hal dalam konteks contoh Anda dengan lebih baik.
blah238
Saya baru saja menemukan posting blog yang sangat baik dari Jason Pardy yang menyediakan template ArcPy yang menggabungkan pola pengkodean untuk modul Python di blogs.esri.com/Dev/blogs/geoprocessing/archive/2011/07/07/21/…
PolyGeo
sejak saat ini tautan ini telah dipindahkan, dan saya yakin itu ada di sini sekarang: blogs.esri.com/esri/arcgis/2011/08/04/pythontemplate
ndimhypervol

Jawaban:

15

Berikut ini contoh pengujian Anda yang dimodifikasi untuk mengimpor modul "utilitas" dalam skrip utama dan memanggil fungsi menggunakan parameter yang dibaca oleh alat skrip:


CopyFeaturesTool.py - Alat skrip yang membaca dalam parameter dan memanggil fungsi dalam modul lain

import CopyFeaturesUtility
import arcpy

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

CopyFeaturesUtility.py - Modul yang memiliki fungsi tunggal copyFeaturesToTempGDB. Dapat diimpor atau dijalankan mandiri. Jika dijalankan mandiri, kode di bawah if __name__ == '__main__'dijalankan.

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)

Saya pikir Anda akan menemukan pendekatan modular ini menjadi jauh lebih efisien dan logis setelah Anda terbiasa. Bagian Modul dalam tutorial Python standar juga merupakan sumber yang bagus untuk memahami cara kerja impor.

Untuk contoh yang lebih spesifik tentang busur, lihat skrip bawaan di C:\Program Files\ArcGIS\Desktop10.0\ArcToolbox\Scriptsfolder Anda .

blah238
sumber
13

Anda dapat melakukannya dengan mengimpor modul (skrip yaitu) ke skrip utama Anda dan memanggil fungsinya. Demo sederhana terkandung dalam dua skrip yang menyertai.

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

untuk program utama dan untuk fungsi-fungsi yang dipanggil

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

Anda hanya perlu memastikan bahwa modul utama dan modul anak ada di folder yang sama. Anda dapat mengirimkan parameter ke modul anak dengan mudah dan jika modul anak membutuhkan akses ke arcpy (dengan asumsi Anda menggunakan arcmap versi 10) cukup berikan referensi padanya.


sumber
6

Mengimpor dan menjalankan fungsi adalah cara yang lebih bersih untuk melakukannya, tetapi demi kelengkapan, ada juga execfilefungsi bawaan ( dokumentasi ) yang akan memungkinkan Anda menjalankan file sewenang-wenang dalam konteks saat ini.

Jason Scheirer
sumber
0

The Metode execfile dijelaskan oleh @JasonScheirer memungkinkan saya untuk mengatur ulang kode saya dengan yang di bawah ini dan memberikan solusi untuk masalah pengujian saya:

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

Namun, ini mungkin terbukti rumit ketika diterapkan pada skrip non-tes yang jauh lebih lama sehingga saya menggunakan karya @ blah238 yang mendukung pendekatan @ DanPatterson dan menghasilkan kode akhir (pengujian) berikut yang melakukan persis apa yang saya butuhkan.

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

dan

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