PowerShell ‘Get-FileHash’ 오류: Python subprocess.Popen에서 cmdlet 인식 문제 해결
개발 과정에서 특정 기능을 실행하기 위해 PowerShell 스크립트를 활용하는 경우가 많습니다. 특히 Python의 subprocess 모듈을 사용해 PowerShell 스크립트를 호출할 때, 로컬 환경에서는 정상적으로 작동하던 스크립트가 갑자기 'Get-FileHash' is not recognized as the name of a cmdlet과 같은 오류를 발생시키며 실행되지 않는 경우가 있습니다. 이 글에서는 이러한 문제의 원인을 심층 분석하고, 구글 SEO 및 사용자 경험(UX)에 최적화된 해결책을 제시합니다.
1. 에러 발생 상황
사용자는 매핑된 드라이브에 있는 PowerShell 스크립트(some.ps1)를 실행하기 위해 Windows 바로 가기(Shortcut)를 사용했습니다. 바로 가기 속성은 다음과 같았습니다.
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File \\some_drive\some_folder\some.ps1 some.ts2
이 바로 가기를 통해 스크립트를 실행했을 때는 아무 문제 없이 정상적으로 작동했습니다. 그러나 동일한 스크립트를 Python의 subprocess.Popen 또는 subprocess.run을 사용하여 호출했을 때 다음과 같은 에러가 발생하며 스크립트가 실행되지 않았습니다.
Get-Command : The term 'Get-FileHash' is not recognized as the name of a cmdlet, function, script file, or operable program.
에러 메시지는 명확하게 Get-FileHash라는 cmdlet을 인식하지 못한다는 것을 나타냅니다.
2. 명확한 발생 원인
이 문제의 핵심 원인은 PowerShell 버전 불일치 또는 subprocess 환경의 차이에 있습니다.
-
PowerShell 버전 문제
Get-FileHashcmdlet은 PowerShell 4.0 버전부터 도입되었습니다. 바로 가기로 스크립트가 정상 작동했다는 것은 사용자의 시스템에 PowerShell 4.0 이상의 버전이 설치되어 있고, 바로 가기가 해당 버전을 성공적으로 호출했음을 의미합니다. Windows 10/11의C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe경로는 사실상 Windows PowerShell 5.1(또는 그 이상)을 실행하는 경우가 많습니다.v1.0이라는 이름은 역사적인 경로일 뿐입니다.하지만 Python의
subprocess.Popen이 스크립트를 실행할 때는, 바로 가기와는 다른 환경에서 PowerShell을 호출할 수 있습니다. 예를 들어,subprocess가 시스템의PATH환경 변수를 제대로 상속받지 못하거나, 의도치 않게 PowerShell의 아주 구형 버전(예: PowerShell 1.0)을 실행하게 되는 상황이 발생할 수 있습니다. PowerShell 1.0에는Get-FileHashcmdlet이 존재하지 않으므로, 이 cmdlet을 인식하지 못하는 오류가 발생하는 것입니다. -
subprocess 실행 환경 차이
subprocess모듈로 외부 프로그램을 실행할 때, 기본적으로 현재 Python 프로세스의 환경 변수(PATH등)를 상속받습니다. 그러나 때로는 환경 변수가 완벽하게 상속되지 않거나, PowerShell이 필요로 하는 특정 모듈 로딩 경로 등이 제대로 설정되지 않는 경우가 있습니다. 이는 PowerShell이 cmdlet을 찾고 로드하는 방식에 영향을 줄 수 있습니다.
3. 해결 방법 및 코드 예시
Get-FileHash cmdlet 인식 문제를 해결하기 위한 가장 효과적인 방법은 subprocess.Popen 호출 시 PowerShell 실행 파일의 정확한 경로를 명시하고, 현재 환경 변수를 올바르게 상속하도록 하는 것입니다.
3.1. PowerShell 실행 파일 경로 명시 및 환경 변수 상속
Python 스크립트에서 PowerShell을 호출할 때, `powershell.exe`의 전체 경로를 직접 지정하고, 현재 Python 프로세스의 모든 환경 변수를 PowerShell 프로세스에 상속하도록 설정합니다. 이를 통해 바로 가기가 작동하는 것과 동일한 PowerShell 환경을 만들어줍니다.
import subprocess
import os
# 1. PowerShell 실행 파일의 정확한 경로 확인
# 대부분의 최신 Windows 시스템에서는 이 경로가 Windows PowerShell 5.1 이상을 가리킵니다.
# (만약 PowerShell Core(pwsh.exe)를 사용한다면 해당 경로를 지정하세요. 예: r"C:\Program Files\PowerShell\7\pwsh.exe")
powershell_path = r"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
# 2. 실행할 PowerShell 스크립트 및 인자 정의
# 매핑된 드라이브 경로는 Python 문자열에서 역슬래시 이스케이프가 필요할 수 있습니다.
ps1_script = r"\\some_drive\some_folder\some.ps1"
ts2_arg = r"some.ts2"
# 3. subprocess 호출을 위한 명령 리스트 구성
command = [
powershell_path,
"-ExecutionPolicy", "Bypass", # 실행 정책 우회 (필요시)
"-File", ps1_script,
ts2_arg
]
print(f"Executing command: {' '.join(command)}")
try:
# 4. subprocess.run 호출: 현재 환경 변수를 상속하여 실행
# env=os.environ.copy()를 통해 Python 프로세스의 환경 변수를 PowerShell 프로세스에 전달합니다.
result = subprocess.run(
command,
capture_output=True, # 표준 출력 및 표준 에러 캡처
text=True, # 출력을 텍스트로 디코딩
check=True, # 0이 아닌 종료 코드가 발생하면 CalledProcessError 예외 발생
env=os.environ.copy() # 현재 환경 변수를 복사하여 전달
)
print("STDOUT:", result.stdout)
if result.stderr:
print("STDERR:", result.stderr)
print("PowerShell script executed successfully!")
except subprocess.CalledProcessError as e:
print(f"Error executing PowerShell script: {e}")
print("STDOUT (on error):", e.stdout)
print("STDERR (on error):", e.stderr)
except FileNotFoundError:
print(f"Error: PowerShell executable not found at '{powershell_path}'. "
f"Please verify the path and ensure PowerShell is installed correctly.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
위 코드에서 가장 중요한 부분은 powershell_path 변수에 powershell.exe의 정확한 전체 경로를 지정하고, env=os.environ.copy()를 subprocess.run (또는 subprocess.Popen) 함수에 전달하는 것입니다. 이렇게 하면 PowerShell이 올바른 버전과 환경 설정으로 실행되어 Get-FileHash를 포함한 필요한 cmdlet을 인식할 수 있게 됩니다.
3.2. PowerShell 버전 확인 및 `pwsh.exe` (PowerShell Core) 사용 고려
현재 시스템에 설치된 PowerShell 버전을 확인하고, 필요한 경우 PowerShell Core (pwsh.exe) 사용을 고려할 수 있습니다.
-
설치된 PowerShell 버전 확인: 명령 프롬프트나 PowerShell에서 다음 명령어를 실행하여 현재 사용 가능한 PowerShell 실행 파일의 경로와 버전을 확인합니다.
-
Windows PowerShell: PowerShell 콘솔에서
$PSVersionTable입력 후PSVersion항목 확인. -
PowerShell Core: PowerShell Core 콘솔에서
$PSVersionTable입력 후PSVersion항목 확인. (설치되어 있다면where.exe pwsh.exe로 경로 확인 가능)
Get-FileHash는 PowerShell 4.0+에서 사용 가능하므로, 최소한 이 버전을 만족하는 PowerShell 실행 파일을 사용해야 합니다. -
-
PowerShell Core (
pwsh.exe) 사용: 만약 시스템에 PowerShell Core (버전 6 이상)가 설치되어 있다면,powershell.exe대신pwsh.exe를 사용하는 것이 좋습니다. PowerShell Core는 더 현대적이고 크로스 플랫폼을 지원하며, 최신 기능과 성능 개선 사항을 포함하고 있습니다.subprocess호출 시powershell_path를C:\Program Files\PowerShell\7\pwsh.exe(또는 설치된 경로)로 변경하여 사용할 수 있습니다.
4. 향후 예방을 위한 팁
이러한 유형의 환경 관련 오류를 사전에 방지하고 문제 해결 시간을 단축하기 위한 몇 가지 팁입니다.
-
PowerShell 버전 표준화: 개발, 테스트, 배포 환경에서 사용되는 PowerShell의 버전이 동일하도록 관리합니다. 이는
Get-FileHash와 같은 특정 cmdlet의 가용성 문제를 방지하는 데 필수적입니다. -
subprocess호출 시 전체 경로 사용: 외부 실행 파일(powershell.exe,python.exe등)을subprocess로 호출할 때는 가능한 한 실행 파일의 전체 경로를 명시적으로 지정하여PATH환경 변수에 의존하는 문제를 줄입니다. -
환경 변수 상속 확인:
subprocess호출 시env=os.environ.copy()를 사용하여 현재 스크립트의 환경 변수를 상속하도록 하는 습관을 들입니다. 필요한 경우,env딕셔너리를 직접 수정하여 특정 환경 변수를 추가하거나 오버라이드할 수 있습니다. -
디버깅 출력 활용: 문제가 발생했을 때, PowerShell 스크립트 내에서
$PSVersionTable을 출력하거나,subprocess호출 전후로os.environ을 출력하여 환경 변수를 비교하면 문제를 진단하는 데 큰 도움이 됩니다. -
try-except블록 사용:subprocess호출을 항상try-except블록으로 감싸서FileNotFoundError,CalledProcessError등 발생 가능한 예외를 처리하고 디버깅 정보를 출력하도록 합니다.
이러한 접근 방식을 통해 Python에서 PowerShell 스크립트를 안정적으로 호출하고, ‘Get-FileHash’와 같은 cmdlet 인식 문제를 효과적으로 해결할 수 있을 것입니다.
![[에러 해결] Python 오프라인 설치 (AppLocker/Windows Store) 0x800704EC 원인과 해결 방법 [에러 해결] Python 오프라인 설치 (AppLocker/Windows Store) 0x800704EC 원인과 해결 방법](https://dev-error.com/wp-content/plugins/contextual-related-posts/default.png)