Select to view content in your preferred language

ArcGIS10 - Run Python Script from .NET

1990
2
09-02-2010 03:04 PM
TonyThatcher
Deactivated User
Ah, growing pains....  Making the painful switch from developing in VBA (which I seem to be able to get done what I need to), to .NET and Python (which is proving to be challenging).

I would like to be able to run scripts that I develop in Python from user forms (Addin Dockable Windows or regular .NET Forms).  Ultimately, I need to be able to pass selections that the user makes in the Form to the Python script as parameters (e.g. Inupt layer1, Input layer2, output name, output GDB, etc.).  But first, I need to be able to run a Python script from a .NET button click.  ESRI posted an example at http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000m0s000000.  I've replaced thier script with my own simple buffering script (see below), but can't seem to get any results.  It seems to run, but no layer is created.  No errors are returned.

#Test Python Script
import arcpy
arcpy.Buffer_analysis("test_lines","bufferer_lines","1000 meters")

This runs fine as in the new Python Window in 10, or as a Script Tool.  So I assume the syntax is fine.  It just will not do anything when run from the .NET button click.  A process seems to run in that it takes about the same amount of time, just no result is generated.  I've even tried outputting it a a .shp file with no luck. 

There don't seem to be many folks running 10 yet, or developing in it, so hopefully this will spark some discussion that will be useful for others.   We really need some examples out there!

-Tony
0 Kudos
2 Replies
TonyThatcher
Deactivated User
Come on folks!  A week and nobody has any thoughts on this?  A lot of looks, though.

Meanwhile I am struggling with a variety of other Python issues and starting to feel that it just is not far enough along in terms of integration with other IDEs and the full suite of ArcGIS tools available through ArcObjects. 

Just a couple of examples:
1) In a Script Tool that runs a Python script, you can create a new Feature Class that is saved in your Geodatabase (or a Shape File if you want to go that route), you just can not add it to your map display.  ArcPy.mapping has the AddLayer function, but this is truly for "layers" (as in .lyr) files.  So you have to already have a .lyr file defined, update the references to any data in the lyr file to your new Feature Class, then add the lyr file to your map or refresh the lyr file that is already in your map. 
2) And this relates to #1 above.  Lets say you need to do a multi-step script where you first create a new data set (e.g. copy an existing Feature Class so you can do some modifications to it), and then you need to select a set of records from that new data set (SelectLayerByAttribute), and then do something like calculate values for those new records or buffer them.  Since you have no way of adding the copied data set to your map, your select fails (the Feature Class you are selecting from only exists on disk).  There may be a way to use Scratch layers or something like that, but the documentation is so thin that I can not find a simple example that shows me how to go about it.  If this were done in a model, then the intermediate Feature Classes could be automatically added to map and used.  So far I can not see a way to add intermediate steps from a Python-based Script Tool to the map.

OK, that's my rant for the time being.  Please ESRI, get some decent documentation for the shift from VBA to .NET and Python!  If this is our future, then make it understandable to the average developer.  I've been programming in ESRI products for 13 years and this latest shift has left me dreaming of simpler day back in Avenue.

-T
0 Kudos
JohnHauck
Frequent Contributor
Don't get me wrong, I love Python and generally advocate it's use. However, it seems in this case that a level of interop is being added that may not be absolutely necessary. You can work with the Geoprocessor class directly from .NET. Could you help me understand why you would like to use Python scripts instead of staying completely with .NET?

Here is an example of how you could call a python script from a .NET button (Add-in in this case) click, get the result from your script,and add it to your current map:

Python Script:
import arcpy, sys

a = sys.argv[1]
b = sys.argv[2]

try:
    result = arcpy.Buffer_analysis(a, b, "1000 meters")
    sys.stdout.write(str(result.getOutput(0)))
except:
    sys.stdout.write("Error")




.NET code:
        protected override void OnClick()
        {
            IMap map = ArcMap.Document.FocusMap;

            IDataset dset = (IDataset)((IFeatureLayer)map.get_Layer(0)).FeatureClass;

            string workspace = dset.Workspace.PathName;
            string inputFC = workspace + "\\" + dset.BrowseName;

            string outputFCName = "myOutput1";
            string outputPath = workspace + "\\" + outputFCName;

            object command = @"C:\techLead_incidents\user_forums\Script1.py"; 
            System.Diagnostics.ProcessStartInfo procStartInfo = new
                System.Diagnostics.ProcessStartInfo("cmd", "/c " + command + " " + inputFC + " " + outputPath);

            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = true;
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo = procStartInfo;
            proc.Start();

            string result = proc.StandardOutput.ReadToEnd();


            addLayer(map, result);

            ArcMap.Application.CurrentTool = null;
        }

        private void addLayer(IMap map, string fullPath)
        {
            string[] pathPart = fullPath.Split('\\');
            
            string fcName = pathPart[pathPart.Length -1];
            string workspace = fullPath.Replace(('\\' + fcName).ToString(), "");

            IWorkspaceFactory pWSFactory = new FileGDBWorkspaceFactoryClass();
            IWorkspace pWorkspace = (IWorkspace)pWSFactory.OpenFromFile(workspace, ArcMap.Application.hWnd);
            IFeatureWorkspace pFWorkspace = (IFeatureWorkspace)pWorkspace;
            IFeatureClass pFClass = (IFeatureClass)pFWorkspace.OpenFeatureClass(fcName);
            IFeatureLayer pFLayer = new FeatureLayerClass();

            pFLayer.FeatureClass = pFClass;

            pFLayer.Name = fcName;
            pFLayer.ShowTips = true;

            map.AddLayer(pFLayer);
        }



You could of course go about this quite a few different ways but I wanted to throw this idea out there and see how it may fit for what you have in mind.
0 Kudos