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:
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:
- the "True" associated with python means python is installed with ArcGIS
- 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