Sunday 25 October 2015

arcgis 10.0 - How can I programmatically get the path of "Python.exe" used by ArcMap


I am working with an add-in of ArcMap in C#. From C# code, I have executed some Python scripts. Now, to run those script, I have hard-coded python path. But this is not portable. So, I want to get the path of the Python executable from the code and use it.


Question:


How can I get the path of the Python executable used by ArcMap from C# code?


EDIT :


From your suggestions, for now I am using "path environment" to get Python path.


//get python path from environtment variable
string GetPythonPath()
{
IDictionary environmentVariables = Environment.GetEnvironmentVariables();

string pathVariable = environmentVariables["Path"] as string;
if (pathVariable != null)
{
string[] allPaths = pathVariable.Split(';');
foreach (var path in allPaths)
{
string pythonPathFromEnv = path + "\\python.exe";
if (File.Exists(pythonPathFromEnv))
return pythonPathFromEnv;
}

}
}

But there is a problem:


When different version of python is installed in my machine, there is no guarantee that, the "python.exe" I am using, ArcGIS also using that.


I don't appreciate using another tool to get "python.exe" path. So, I really think if there any way to get the path from registry key. For "ArcGIS10.0" registry looks like: enter image description here


And for that, I am thinking about following way to get the path:


//get python path from registry key
string GetPythonPath()
{

const string regKey = "Python";
string pythonPath = null;
try
{
RegistryKey registryKey = Registry.LocalMachine;
RegistryKey subKey = registryKey.OpenSubKey("SOFTWARE");
if (subKey == null)
return null;

RegistryKey esriKey = subKey.OpenSubKey("ESRI");

if (esriKey == null)
return null;

string[] subkeyNames = esriKey.GetSubKeyNames();//get all keys under "ESRI" key
int index = -1;
/*"Python" key contains arcgis version no in its name. So, the key name may be
varied version to version. For ArcGIS10.0, key name is: "Python10.0". So, from
here I can get ArcGIS version also*/
for (int i = 0; i < subkeyNames.Length; i++)
{

if (subkeyNames[i].Contains("Python"))
{
index = i;
break;
}
}
if(index < 0)
return null;
RegistryKey pythonKey = esriKey.OpenSubKey(subkeyNames[index]);


string arcgisVersion = subkeyNames[index].Remove(0, 6); //remove "python" and get the version
var pythonValue = pythonKey.GetValue("Python") as string;
if (pythonValue != "True")//I guessed the true value for python says python is installed with ArcGIS.
return;

var pythonDirectory = pythonKey.GetValue("PythonDir") as string;
if (pythonDirectory != null && Directory.Exists(pythonDirectory))
{
string pythonPathFromReg = pythonDirectory + "ArcGIS" + arcgisVersion + "\\python.exe";
if (File.Exists(pythonPathFromReg))

pythonPath = pythonPathFromReg;
}
}
catch (Exception e)
{
MessageBox.Show(e + "\r\nReading registry " + regKey.ToUpper());
pythonPath = null;
}
return pythonPath ;
}


But before using the second procedure, I need to be sure about my guesses. Guesses are:



  1. the "True" associated with python means python is installed with ArcGIS

  2. ArcGIS 10.0 and upper version's registry key will be written in same process.


Please help me to get any clarification about my guesses.



Answer



I took your second code example, made it work on both 64 and 32-bit OS's, and simplified it a bit. Works for me at 10.1 on Windows 7 64-bit, but obviously you should test it on as many environments as possible, and add back in whatever defensive programming checks you think are necessary.


After testing clean-installing ArcGIS Desktop 10.1 without Python, I found that it does not include the Python10.x subkey, let alone the "Python" True/False value (still not sure what that is for, maybe contact ESRI support if you must know).



string GetPythonPath()
{
string pythonPath = null;
var localmachineKey = Registry.LocalMachine;
// Check whether we are on a 64-bit OS by checking for the Wow6432Node key (32-bit version of the Software registry key)
var softwareKey = localmachineKey.OpenSubKey(@"SOFTWARE\Wow6432Node"); // This is the correct key for 64-bit OS's
if (softwareKey == null) {
softwareKey = localmachineKey.OpenSubKey("SOFTWARE"); // This is the correct key for 32-bit OS's
}
var esriKey = softwareKey.OpenSubKey("ESRI");

var realVersion = (string)esriKey.OpenSubKey("ArcGIS").GetValue("RealVersion"); // Get the "real", canonical version of ArcGIS
var shortVersion = String.Join(".", realVersion.Split('.').Take(2).ToArray()); // Get just the Major.Minor part of the version number, e.g. 10.1
var pythonKey = esriKey.OpenSubKey("Python" + shortVersion); // Open the Python10.x sub-key
if (pythonKey == null) {
throw new InvalidOperationException("Python not installed with ArcGIS!");
}
var pythonDirectory = (string)pythonKey.GetValue("PythonDir");
if (Directory.Exists(pythonDirectory))
{
// Build path to python.exe

string pythonPathFromReg = Path.Combine(Path.Combine(pythonDirectory, "ArcGIS" + shortVersion), "python.exe");
if (File.Exists(pythonPathFromReg)) {
pythonPath = pythonPathFromReg;
}
}
return pythonPath;
}

On a Desktop 10.1 machine with Python, this returns C:\Python27\ArcGIS10.1\python.exe. On a Desktop 10.1 machine without Python, this raises an InvalidOperationException due to the Python10.x key not being present.


Hopefully this helps you with whatever you're trying to actually accomplish, which is -- amazingly -- still not clear to me.



No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...