A common coding pattern used in AML was to run an AML (with parameters) inside another AML.
An application that I'm currently developing would benefit from being able to run a Python script (with parameters) within another Python script.
However, this does not seem to be at all straightforward.
Using ArcGIS 10, I'm experimenting with wrapping the "inner" Python script into an ArcGIS tool that has the parameters. I thought it would be a simple matter to have the "outer" Python script use arcpy.ImportToolbox to import the toolbox and then run the tool(s) within it. However, in testing so far all my attempts to run the "inner" tool from the "outer" script appear to simply skip the "inner" tool (no error is thrown).
Any thoughts on how to do this are welcome. In the meantime I'll try to create some simple test code to illustrate better what I am trying to describe.
Test code is now here ...
My testinner.py script is:
inputString = arcpy.GetParameterAsText(0) newFC = "C:\\Temp\\test.gdb\\" + inputString arcpy.Copy_management("C:\\Temp\\test.gdb\\test",newFC)
My testouter.py script is:
import arcpy inputString1 = arcpy.GetParameterAsText(0) inputString2 = arcpy.GetParameterAsText(1) arcpy.ImportToolbox("C:\\Temp\\test.tbx") arcpy.testinner_test(inputString1) arcpy.testinner_test(inputString2)
For testinner.py its tool needs a single String parameter.
For testouter.py its tool needs two String parameters
The two tools are placed in a test.tbx.
The test.gdb just needs a single empty feature class called test.
Once you have the above assembled, running the testinner tool with a string like 'abc' passed in as its parameter should result in feature class 'test' being copied to one called 'abc' OK.
But when you try running the testouter tool with two strings like 'uvw' and 'xyz' as its parameters, the testinner tool within testouter.py seems to run OK once, but sends ArcMap 10 SP2 on Vista SP2 to a Serious Application Error when trying to use it the second time.
The same test using Windows XP SP3 and ArcGIS Desktop 10 SP2 also produces a Serious Application Error at the same point.
The execfile method described by Jason allowed me to rearrange my code to that below and provides a solution to my test problem:
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")
However, this may prove cumbersome when applied to non-test script(s) which are much longer so I used blah238's generous work that endorsed Dan's approach (Jason also endorsed Dan's approach I may add) and came up with the following final (test) code that does exactly what I need.
# 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)
Many thanks to Dan, Jason and blah238 for helping me.