C\#python.exe 를 호출 하여 arcpy 방식 을 사용 합 니 다.

7382 단어 C#python.exearcpy
배경
환경:ArcGis 10.2.2.C\#개발 프로그램 은 데스크 톱 의 python 환경(32 비트)을 호출 하여 데이터 처리 분석 을 해 왔 습 니 다.그러나 데이터 양 이 많 을 때 메모리 자원 이 부족 한 상황 이 발생 했다.그래서 64 비트 python 환경 으로 바 꾸 기로 했 습 니 다.
문제 에 봉착 하 다
C\#Process.Start()를 통 해 64 비트 python.exe 를 호출 합 니 다.Debug 모드 에 서 는 문제 가 없 지만 exe 를 직접 실행 하면 Process finished with exit code-1073741819(0xC 0000005)를 잘못 알 립 니 다.지향 이상.
문 제 를 분석 하 다
나중에 arcpy 모듈 로 인해 이 모듈 의 내용 을 없 애 면 실행 되 고 import arcpy 는 실행 되 지 않 는 다 는 것 을 알 게 되 었 습 니 다.arcpy 를 사용 하여 데이터 처 리 를 하 는 이상 import arcpy 도 안 된다 면 뭘 하 겠 습 니까?그래서 프로그램 Debug 모드 와 Run 모드 의 차 이 를 찾기 시작 했다.
프로그램 에서 ProcessStartInfo 클래스 를 사용 하여 시작 하 는 python.exe 프로 세 스 입 니 다.그 문 제 는 기본적으로 여기에서 나 옵 니 다.검사 코드 첨부:

var start = new ProcessStartInfo
{
 WorkingDirectory = Environment.CurrentDirectory,
 FileName = sInterpreterPath,
 UseShellExecute = false,
 ErrorDialog = true,
 CreateNoWindow = true,
 RedirectStandardOutput = true,
 RedirectStandardInput = true,
 Arguments = sParam
};
using (Process process = Process.Start(start))
{
 var a = start.Environment;
 var b = a.Keys.ToList();
 b.Sort();
 var sss = "";
 foreach (var it in b)
 {
 sss = $"{sss}
{it}------->{a[it]}"; } sss = sss.Trim(); using (StreamReader reader = process.StandardOutput) { var sResult = ""; while (!reader.EndOfStream) { sResult = $"{sResult}
{reader.ReadLine()}"; } sResult = sResult.Trim(); MessageBox.Show(sResult); } MessageBox.Show("ExitCode is " + process.ExitCode); }
그래서 Debug 모드 에서 Run 모드 에서 의 프로 세 스 환경 변 수 를 비교 했다.

두 환경 을 뚜렷하게 볼 수 있 는COMPAT_레이 어 값 은 달라.찾 아 봤 는데COMPAT_레이 어 는 버 전 호 환 관련 매개 변수 입 니 다.저 는 32 비트 프로그램 에서 64 비트 python.exe 를 호출 하기 때문에 이 매개 변수 로 인 한 문제 라 고 의심 합 니 다.RunAsAdmin 은 관리자 로 실행 되 고 Installer 는 설치 도구 라 고 설명 합 니 다.
문 제 를 해결 하 다
이 가능 하 다,~할 수 있다,...COMPAT_레이 어가 다 르 기 때문에 생 긴 문제 이 므 로 증상 에 맞 게 약 을 처방 할 수 있 습 니 다.이제 Run 의 값 도 RunAsAdmin 으로 설정 합 니 다.다음 코드 추가:
start.EnvironmentVariables["__COMPAT_LAYER"] = "RunAsAdmin";
start.Environment["__COMPAT_LAYER"] = "RunAsAdmin";
다시 운행 하 는데 성공 하 다 니.
다음은 C\#64 를 Python.exe 처리 스 크 립 트 코드 로 호출 합 니 다.

/// <summary>
///   Python  
/// </summary>
/// <param name="sScriptPath">    </param>
/// <param name="lstParam">    </param>
/// <returns>    </returns>
public bool RunScript(string sScriptPath, List<string> lstParam)
{
 var bResult = false;
 try
 {
 if (!File.Exists(sScriptPath))
 throw new Exception($"  {sScriptPath}   !");
 var sInterpreterPath = @"E:\ArcGIS\Python27\ArcGISx6410.2\python.exe";
 var sParam = $"{sScriptPath}";
 if (null != lstParam && 0 < lstParam.Count)
 {
 var sArgument = "\"" + string.Join("\" \"", lstParam) + "\"";
 sParam = $"\"{sParam}\" {sArgument}";
 }
 var start = new ProcessStartInfo
 {
 WorkingDirectory = Environment.CurrentDirectory,
 FileName = sInterpreterPath,
 UseShellExecute = false,
 ErrorDialog = true,
 CreateNoWindow = true,
 RedirectStandardOutput = true,
 RedirectStandardInput = true,
 Arguments = sParam
 };
 start.EnvironmentVariables["__COMPAT_LAYER"] = "RunAsAdmin";
 start.Environment["__COMPAT_LAYER"] = "RunAsAdmin";
 using (Process process = Process.Start(start))
 {
 using (StreamReader reader = process.StandardOutput)
 {
 var sResult = "";
 while (!reader.EndOfStream)
 {
  sResult = $"{sResult} 
{reader.ReadLine()}"; } sResult = sResult.Trim(); MessageBox.Show(sResult); } MessageBox.Show("ExitCode is " + process.ExitCode); } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } return bResult; }
추가 지식:C\#레 지 스 트 에서 ArcPy 의 python.exe 설치 위 치 를 얻 습 니 다.
왜 이 위 치 를 가 져 옵 니까?
C\#에서 명령 을 호출 하여 Python 스 크 립 트 를 실행 할 때 Python 해석 기 는 필수 적 인 도구 입 니 다.ArcGIS 10.2.2 설치 시 기본적으로 Python 을 설치 하지만 사용자 마다 Python 을 다른 위치 에 설치 할 수 있 습 니 다.예 를 들 어 본인 은 기본 CD 가 아 닌 D 디스크 에 설치 할 수 있 습 니 다.
그러면 우리 시스템 이 다른 사용자 에 게 사용 할 때 Python 해석 기 즉 python.exe 파일 위 치 를 찾 아야 도구 호출 을 정상적으로 실행 할 수 있 습 니 다.
물론 환경 변수 에 파일 위 치 를 기록 할 수 있 습 니 다.이 경 로 는 전체 경 로 를 가 져 올 필요 가 없습니다.본 고 는 이런 상황 을 고려 하지 않 는 다.
이 위 치 를 어떻게 가 져 옵 니까?
여러 대의 컴퓨터 를 비교 해 보면 파 이 썬 이 설치 되면 레 지 스 트 에'HKEYLOCAL_MACHINE\\SOFTWARE\Microsoft\Windows\CurrentVersion\\Installer\UserData\S-1-5-18\\Components"아래 에 키"9A6767D28A88AEB44AD0AE3AA51002C 0"을 자동 으로 만 듭 니 다.
이 키 아래 에 값 이 있 습 니 다.해당 하 는 데 이 터 는 python.exe 의 전체 경로 입 니 다.우 리 는 이 데 이 터 를 읽 기만 하면 python.exe 위 치 를 얻 을 수 있 습 니 다.

C\#코드 는 다음 과 같 습 니 다:

  /// <summary>
  /// Python.exe            (  ArcGIS  Python       )
  /// </summary>
  private static readonly string RegistryPythonDefaultKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\";
  /// <summary>
  /// Python.exe          (  ArcGIS  Python       )
  /// </summary>
  private static readonly string RegistryPythonTargetKey = "9A6767D28A88AEB44AD0AE3AA51002C0";
  /// <summary>
  ///   Python.exe    
  /// </summary>
  /// <returns></returns>
  private static string GetPythonPath()
  {
   var sPythonPath = "";
   try
   {
    var registryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
     Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32); //      
    var targetSubKey = registryKey.OpenSubKey(Path.Combine(RegistryPythonDefaultKey, RegistryPythonTargetKey));
    var lstName = targetSubKey.GetValueNames();
    foreach (var sName in lstName)
    {
     var sValue = targetSubKey.GetValue(sName) + string.Empty;
     if (!sValue.EndsWith("python.exe", StringComparison.OrdinalIgnoreCase) || !File.Exists(sValue))
     {
      continue;
     }
     sPythonPath = sValue;
     break;
    }
   }
   catch (Exception ex)
   {
    SysConfig.Model.LogServices.WriteExceptionLog(ex, "GetPythonPath");
   }
   return sPythonPath;
  }
주의해 야 할 곳?
레 지 스 트 를 열 때 기계 의 위 치 를 판단 해 야 합 니 다.32 비트 와 64 비트 레 지 스 트 의 위치 가 다 릅 니 다.다음 과 같 습 니 다.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components
이상 의 C\#python.exe 를 호출 하여 arcpy 방식 을 사용 하 는 것 은 바로 편집장 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.여러분 께 참고 가 되 고 많은 응원 을 바 랍 니 다.

좋은 웹페이지 즐겨찾기