PEP 514 – Windows 레지스트리의 Python 등록
- Author:
- Steve Dower <steve.dower at python.org>
- BDFL-Delegate:
- Paul Moore <p.f.moore at gmail.com>
- Status:
- Active
- Type:
- Informational
- Created:
- 02-Feb-2016
- Post-History:
- 02-Feb-2016, 01-Mar-2016, 18-Jul-2016
- Resolution:
- Python-Dev message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 서드파티 설치 프로그램이 자신의 설치를 등록하고, 도구와 애플리케이션이 사용자 컴퓨터의 모든 Python 환경을 감지하여 올바르게 표시할 수 있도록 Python 레지스트리 키의 스키마를 정의합니다. 이 PEP는 Python 구현의 변경을 제안하지 않습니다.
외부 도구가 자동으로 찾을 수 있기를 원하는 경우가 아니라면 Python 환경을 등록할 필요는 없습니다. 이는 Windows에만 해당하므로, 이러한 도구는 대부분 GUI 애플리케이션일 것으로 예상됩니다. 그러나 콘솔 애플리케이션도 등록된 정보를 활용할 수 있습니다. 이 PEP는 제공될 수 있는 정보를 다루지만, 이 정보를 실제로 어떻게 표시하고 사용할지는 도구 설계자에게 맡깁니다.
이 스키마는 적어도 Python 2.5 이후로 공식 설치 프로그램이 사용해 온 레지스트리 값과 일치하며, 해석 동작은 공식 Python 릴리스의 동작과 일치합니다. 전체 정보를 등록하지 않는 CPython 버전도 도구가 올바르게 감지할 수 있도록 몇 가지 하위 호환성 규칙을 제공합니다.
동기
공식 Python 설치 프로그램은 Windows에 설치될 때 다른 애플리케이션이 찾고 감지할 수 있도록 레지스트리 키를 만듭니다. 이를 통해 설치 프로그램이나 IDE 같은 도구가 사용자의 Python 설치를 자동으로 감지하고 표시할 수 있습니다. 예를 들어 PEP 397 py.exe 런처와 PyCharm, Visual Studio 같은 편집기는 이미 이 정보를 활용하고 있습니다.
배포판에서 사용하는 것과 같은 서드파티 설치 프로그램도 보통 같은 목적으로 동일한 키를 만듭니다. 레지스트리를 사용하여 Python 설치를 감지하는 도구는 대부분 공식 설치 프로그램이 사용하는 키만 검사합니다. 그 결과 다른 도구가 찾을 수 있기를 원하는 서드파티 설치는 이 값들을 덮어쓰게 되고, 이로 인해 사용자가 원래의 Python 설치를 “잃어버리는” 일이 자주 발생합니다.
서드파티 설치가 자신을 고유하게 등록할 수 있는 레지스트리 키 레이아웃을 기술하고, 사용 가능한 모든 Python 설치를 찾는 방법에 대한 지침을 도구 개발자에게 제공함으로써 이러한 충돌을 방지할 수 있을 것입니다. 또한 이 기회에 잘 알려진 메타데이터를 몇 가지 추가하여 사용자에게 더 많은 정보를 보여 줄 수 있도록 합니다.
정의
“레지스트리 키”는 레지스트리 안에서 파일 시스템 경로에 해당하는 것입니다. 각 키는 “하위 키”(키 안에 중첩된 키)와 “값”(키에 붙은, 이름과 타입이 있는 속성)을 포함할 수 있습니다. Windows에서는 설정 파일이 들어 있는 디렉터리와 거의 같은 방식으로 이들을 사용하여 설정을 저장합니다.
HKEY_CURRENT_USER는 현재 로그인한 사용자의 설정 루트이며, 일반적으로 이 사용자는 이 루트 아래의 모든 설정을 읽고 쓸 수 있습니다.
HKEY_LOCAL_MACHINE은 모든 사용자의 설정 루트입니다. 일반적으로 모든 사용자가 이 설정을 읽을 수 있지만, 수정은 관리자만 할 수 있습니다. 보통은 HKEY_CURRENT_USER 아래의 값이 HKEY_LOCAL_MACHINE의 값보다 우선합니다.
64비트 Windows에서 HKEY_LOCAL_MACHINE\Software\Wow6432Node는 특수한 키로, 32비트 프로세스는 Software 키에 직접 접근하는 대신 이 키를 투명하게 읽고 씁니다.
Windows의 레지스트리 리디렉션에 대한 자세한 문서는 MSDN 라이브러리 [1]에서 확인할 수 있습니다.
구조
한 컴퓨터에는 Python 환경의 컬렉션이 하나 있다고 간주하며, 이 컬렉션은 컴퓨터의 사용자마다 다를 수 있습니다. 각 환경의 설치 옵션에 따라 컬렉션이 저장될 수 있는 레지스트리 위치는 세 곳입니다:
HKEY_CURRENT_USER\Software\Python\<Company>\<Tag>
HKEY_LOCAL_MACHINE\Software\Python\<Company>\<Tag>
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\<Company>\<Tag>
공식 Python 릴리스는 Company로 PythonCore를, Tag로 sys.winver 값을 사용합니다. Company PyLauncher는 예약되어 있습니다. 그 밖의 등록된 환경은 Company와 Tag에 어떤 값이든 사용할 수 있습니다. 권장 사항은 이 문서의 뒷부분에서 제시합니다.
Company-Tag 쌍은 대소문자를 구분하지 않으며, 각 환경을 고유하게 식별합니다. 도구의 목적과 용도에 따라 Company-Tag 쌍 사이의 충돌을 해결하는 방법으로 두 가지를 제안합니다.
설치된 모든 환경을 나열하는 도구는 Company-Tag 쌍이 일치하더라도 해당 환경을 모두 포함하도록 선택할 수 있습니다. 이러한 도구는 등록이 사용자별인지 머신별인지, 그리고 어느 등록의 우선순위가 더 높은지를 사용자가 쉽게 식별할 수 있도록 해야 합니다.
py.exe 런처처럼 Company-Tag 쌍을 기준으로 등록된 모든 환경 중에서 설치된 환경 하나를 선택하려는 도구는 HKEY_LOCAL_MACHINE에 있는 일치하는 환경 대신 항상 HKEY_CURRENT_USER에 등록된 환경을 선택해야 합니다.
HKEY_LOCAL_MACHINE\Software\Python과 HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python 사이의 충돌은 인터프리터의 64비트 버전과 32비트 버전이 같은 Tag를 가질 때에만 발생해야 합니다. 이 경우 도구는 자신의 용도에 더 적합한 쪽을 선택해야 합니다.
제공된 정보(또는 정보의 부재)로부터 등록된 환경을 사용할 수 없다고 도구가 판단할 수 있다면, 그 환경을 사용자에게 보여 줄 의무는 없습니다.
하위 호환성 절에서 논의하는 경우를 제외하면 Company와 Tag 값은 도구에게 불투명한 값으로 간주되며, 그 텍스트로부터 인터프리터에 관한 어떠한 정보도 추론해서는 안 됩니다. 그러나 일부 도구는 Company와 Tag 값을 사용자에게 표시할 수 있으므로, Tag가 사용자가 관련 환경을 식별하는 데 도움이 되는 것이 이상적입니다.
Python 환경은 외부 도구가 자동으로 찾을 수 있기를 원하는 경우가 아니라면 스스로를 등록할 필요가 없습니다.
하위 호환성
Python 3.4 이하 버전은 sys.winver에서 32비트 빌드와 64비트 빌드를 구분하지 않았습니다. 그 결과 이 체계에서는 Tag가 중복되므로 32비트 인터프리터와 64비트 인터프리터를 모두 올바르게 나란히 설치하는 것이 불가능합니다.
하위 호환성을 보장하기 위해 애플리케이션은 Tag가 일치하더라도 다음 두 레지스트리 키 아래에 나열된 환경을 서로 다른 환경으로 취급해야 합니다:
HKEY_LOCAL_MACHINE\Software\Python\PythonCore\<Tag>
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\PythonCore\<Tag>
HKEY_CURRENT_USER 아래에 나열된 환경은 위의 두 키 모두와 구별되는 환경으로 취급할 수 있으며, 이 경우 같은 Tag로 세 개의 환경이 발견될 수 있습니다. 또는 도구가 사용자별 환경이 64비트인지 32비트인지 판단하여 그 환경에 머신별 환경보다 높은 우선순위를 부여할 수 있으며, 이 경우 발견되는 환경은 최대 두 개가 됩니다.
3.5 이전 Python의 64비트 버전과 32비트 버전이 현재 사용자용으로 설치된 경우에는 두 버전이 나란히 설치되어 있는지 감지하는 것이 불가능합니다. Python 3.5 이후 버전은 64비트 버전과 32비트 버전에 항상 서로 다른 Tag를 사용합니다.
다음 절에서는 등록할 수 있는, 사용자에게 보이는 정보를 설명합니다. Python 3.5 이하 버전에서는 이 정보를 전혀 사용할 수 없지만, PythonCore 키에 대해서는 대체 기본값이 지정되어 있습니다.
다른 Company 이름 아래에 등록된 환경에는 하위 호환성 요구 사항이 없으며, 나란히 설치하는 것을 지원하려면 서로 다른 Tag를 사용해야 합니다. 이러한 등록 정보를 사용하는 도구는 사용자의 설정을 우선하는 것 외에는 Tag를 구별할 필요가 없습니다.
Company
키의 Company 부분은 관련된 환경을 묶고, Tag가 적절하게 네임스페이스로 구분되도록 하기 위한 것입니다. 키 이름은 공백 없는 영숫자로 이루어져야 하며, 고유할 가능성이 높아야 합니다. 예를 들어 상표명(권장), 호스트 이름, 또는 최후의 수단으로 UUID가 적절합니다:
HKEY_CURRENT_USER\Software\Python\ExampleCorp
HKEY_CURRENT_USER\Software\Python\www.example.com
HKEY_CURRENT_USER\Software\Python\6C465E66-5A8C-4942-9E6A-D29159480C60
회사 이름 PyLauncher는 PEP 397 런처(py.exe)용으로 예약되어 있습니다. 이 회사 이름은 이 규칙을 따르지 않으므로 도구는 이를 무시해야 합니다.
DisplayName이라는 문자열 값이 있으면, 사용자에게 환경의 제조사/개발자/배포자를 식별해 보여 주는 데 이 값을 사용해야 합니다. 그렇지 않으면 키의 이름을 사용해야 합니다. (PythonCore의 경우, 기본 표시 이름은 “Python Software Foundation”입니다.)
SupportUrl이라는 문자열 값이 있으면, 이 값을 표시하거나 다른 방식으로 사용하여 사용자를 환경과 관련된 웹 사이트로 안내할 수 있습니다. (PythonCore의 경우, 기본 지원 URL은 “http://www.python.org/”입니다.)
전체 예시는 다음과 같을 수 있습니다:
HKEY_CURRENT_USER\Software\Python\ExampleCorp
(Default) = (value not set)
DisplayName = "Example Corp"
SupportUrl = "http://www.example.com"
Tag
키의 Tag 부분은 한 회사가 제공하는 환경 중에서 특정 환경을 고유하게 식별하기 위한 것입니다. 키 이름은 공백 없는 영숫자여야 하며, 설치가 달라져도 일정하게 유지되어야 합니다. 예를 들어 Python 언어 버전, UUID 또는 부분/전체 해시는 적절하지만, 설치 디렉터리나 현재 머신의 특정 측면에 기반한 Tag는 적절하지 않을 수 있습니다. 예를 들면 다음과 같습니다:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy
HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66
일부 도구는 사용자에게 명령줄에 Tag를 입력하도록 요구할 것으로 예상되며, Tag가 모든 Python 설치에 걸쳐 고유하다면 Company는 선택 사항일 수 있습니다. 짧고, 사람이 읽을 수 있으며, 입력하기 쉬운 Tag를 권장하며, 가능하다면 다른 모든 Company에 걸쳐 고유할 가능성이 높은 값을 선택하십시오.
DisplayName이라는 문자열 값이 있으면, 사용자에게 환경을 식별해 보여 주는 데 이 값을 사용해야 합니다. 그렇지 않으면 키의 이름을 사용해야 합니다. (PythonCore의 경우, 기본값은 “Python “ 뒤에 Tag를 붙인 값입니다.)
SupportUrl이라는 문자열 값이 있으면, 이 값을 표시하거나 다른 방식으로 사용하여 사용자를 환경과 관련된 웹 사이트로 안내할 수 있습니다. (PythonCore의 경우, 기본값은 “http://www.python.org/”입니다.)
Version이라는 문자열 값이 있으면, 환경의 버전을 식별하는 데 이 값을 사용해야 합니다. 이 값은 환경이 구현하는 Python의 버전과는 무관합니다. (PythonCore의 경우, 기본값은 Tag의 처음 세 문자입니다.)
SysVersion이라는 문자열 값이 있으면, 이 값은 인터프리터에서 sys.version_info가 반환하는 버전과 일치하는 x.y 또는 x.y.z 형식이어야 합니다. 생략하면 Python 버전을 알 수 없습니다. (PythonCore의 경우, 기본값은 Tag의 처음 세 문자입니다.)
SysArchitecture라는 문자열 값이 있으면, 이 값은 platform.architecture()가 반환하는 튜플의 첫 번째 요소와 일치해야 합니다. 일반적으로 이 값은 “32bit” 또는 “64bit”입니다. 생략하면 아키텍처를 알 수 없습니다. (PythonCore의 경우, HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python 아래 또는 32비트 운영 체제의 어느 위치에든 등록되면 아키텍처는 “32bit”이고, 64비트 머신에서 HKEY_LOCAL_MACHINE\Software\Python 아래에 등록되면 “64bit”이며, HKEY_CURRENT_USER 아래에 등록되면 알 수 없습니다.)
이 값들은 각각 권장되지만 선택 사항이라는 점에 유의하십시오. SysVersion 또는 SysArchitecture를 생략하면 일부 도구가 해당 환경을 올바르게 지원하지 못할 수 있습니다. 전체 예시는 다음과 같을 수 있습니다:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy
(Default) = (value not set)
DisplayName = "Example Py Distro 3"
SupportUrl = "http://www.example.com/distro-3"
Version = "3.0.12345.0"
SysVersion = "3.6.0"
SysArchitecture = "64bit"
InstallPath
환경 키 아래에 InstallPath 키를 만들어야 합니다. 이 키의 이름은 항상 InstallPath이며, 기본값은 sys.prefix와 일치해야 합니다:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6\InstallPath
(Default) = "C:\ExampleCorpPy36"
ExecutablePath라는 문자열 값이 있으면, 이 값은 python.exe(또는 그에 상응하는) 실행 파일의 전체 경로여야 합니다. 생략하면 해당 환경은 실행할 수 없습니다. (PythonCore의 경우, 기본값은 (Default) 값이 참조하는 디렉터리에 있는 python.exe 파일입니다.)
ExecutableArguments라는 이름의 문자열 값이 있으면, 도구는 ExecutablePath를 실행할 때 그 값을 첫 번째 인자로 사용해야 합니다. 도구는 이 인자들 뒤에 다른 인자를 추가할 수 있으며, 표준 Python 명령줄 옵션을 사용할 수 있으리라고 기대하는 것이 합당합니다.
WindowedExecutablePath라는 이름의 문자열 값이 있으면, 이 값은 pythonw.exe (또는 그에 상응하는) 실행 파일의 경로여야 합니다. 생략된 경우 기본값은 ExecutablePath 값이며, 그 값마저 생략되면 이 환경은 실행할 수 없습니다. (PythonCore의 경우 기본값은 (Default) 값이 가리키는 디렉터리에 있는 pythonw.exe 파일입니다.)
WindowedExecutableArguments라는 이름의 문자열 값이 있으면, 도구는 WindowedExecutablePath를 실행할 때 그 값을 첫 번째 인자로 사용해야 합니다. 도구는 이 인자들 뒤에 다른 인자를 추가할 수 있으며, 표준 Python 명령줄 옵션을 사용할 수 있으리라고 기대하는 것이 합당합니다.
완전한 예는 다음과 같습니다:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy\InstallPath
(Default) = "C:\ExampleDistro30"
ExecutablePath = "C:\ExampleDistro30\ex_python.exe"
ExecutableArguments = "--arg1"
WindowedExecutablePath = "C:\ExampleDistro30\ex_pythonw.exe"
WindowedExecutableArguments = "--arg1"
도움말
환경 키 아래에 Help 키를 만들 수 있습니다. 이 키가 있다면 항상 Help라는 이름을 가지며, 기본값은 없습니다.
Help의 각 하위 키는 해당 환경과 관련된 문서 파일, 도구 또는 URL을 지정합니다. 하위 키의 이름은 무엇이든 될 수 있으며, 기본값은 os.startfile 또는 그에 상응하는 함수에 전달하기에 적합한 문자열입니다.
DisplayName이라는 이름의 문자열 값이 있으면, 사용자에게 도움말 파일을 식별시키는 데 이 값을 사용해야 합니다. 그렇지 않으면 키 이름을 사용해야 합니다.
완전한 예는 다음과 같습니다:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66\Help
Python\
(Default) = "C:\ExampleDistro30\python36.chm"
DisplayName = "Python Documentation"
Extras\
(Default) = "http://www.example.com/tutorial"
DisplayName = "Example Distro Online Tutorial"
기타 키
Company-Tag 쌍 아래의 다른 모든 하위 키는 개별 용도로 자유롭게 사용할 수 있습니다.
공식 CPython 릴리스는 전통적으로 이 공간의 특정 키를 사용하여 Python 표준 라이브러리와 기타 설치된 모듈의 위치를 결정해 왔습니다. 이 동작은 주로 하위 호환성을 위해 유지됩니다. 하지만 이 값들을 읽는 코드가 인터프리터에 내장되어 있으므로, 수정되지 않은 인터프리터를 사용하는 서드파티 배포판은 PythonCore에 기록된 값의 영향을 받을 수 있습니다.
예제 코드
이 예제 코드는 레지스트리를 열거하여, 환경을 시작하는 데 사용할 수 있는 Company-Tag 쌍과 대상 실행 파일을 표시합니다. 각 태그에 대해 가장 선호되는 대상만 표시합니다. PythonCore의 하위 호환 처리는 생략했지만 뒤의 예제에서 보여 줍니다:
# Display most-preferred environments.
# Assumes a 64-bit operating system
# Does not correctly handle PythonCore compatibility
import winreg
def enum_keys(key):
i = 0
while True:
try:
yield winreg.EnumKey(key, i)
except OSError:
break
i += 1
def get_value(key, value_name):
try:
return winreg.QueryValue(key, value_name)
except FileNotFoundError:
return None
seen = set()
for hive, key, flags in [
(winreg.HKEY_CURRENT_USER, r'Software\Python', 0),
(winreg.HKEY_LOCAL_MACHINE, r'Software\Python', winreg.KEY_WOW64_64KEY),
(winreg.HKEY_LOCAL_MACHINE, r'Software\Python', winreg.KEY_WOW64_32KEY),
]:
with winreg.OpenKeyEx(hive, key, access=winreg.KEY_READ | flags) as root_key:
for company in enum_keys(root_key):
if company == 'PyLauncher':
continue
with winreg.OpenKey(root_key, company) as company_key:
for tag in enum_keys(company_key):
if (company, tag) in seen:
if company == 'PythonCore':
# TODO: Backwards compatibility handling
pass
continue
seen.add((company, tag))
try:
with winreg.OpenKey(company_key, tag + r'\InstallPath') as ip_key:
exec_path = get_value(ip_key, 'ExecutablePath')
exec_args = get_value(ip_key, 'ExecutableArguments')
if company == 'PythonCore' and not exec_path:
# TODO: Backwards compatibility handling
pass
except OSError:
exec_path, exec_args = None, None
if exec_path:
print('{}\\{} - {} {}'.format(company, tag, exec_path, exec_args or ''))
else:
print('{}\\{} - (not executable)'.format(company, tag))
이 예제는 현재 사용자의 PythonCore 항목만 검색합니다. 데이터가 없는 경우에는 이 PEP 앞부분에서 설명한 기본값으로 대체합니다. 이 기본값은 PythonCore 아래에서만 사용된다는 점에 유의하십시오. 다른 등록 정보에는 기본값이 전혀 없습니다:
# Only lists per-user PythonCore registrations
# Uses fallback values as described in PEP 514
import os
import winreg
def enum_keys(key):
i = 0
while True:
try:
yield winreg.EnumKey(key, i)
except OSError:
break
i += 1
def get_value(key, value_name):
try:
return winreg.QueryValue(key, value_name)
except FileNotFoundError:
return None
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Python\PythonCore") as company_key:
print('Company:', get_value(company_key, 'DisplayName') or 'Python Software Foundation')
print('Support:', get_value(company_key, 'SupportUrl') or 'http://www.python.org/')
print()
for tag in enum_keys(company_key):
with winreg.OpenKey(company_key, tag) as tag_key:
print('PythonCore\\' + tag)
print('Name:', get_value(tag_key, 'DisplayName') or ('Python ' + tag))
print('Support:', get_value(tag_key, 'SupportUrl') or 'http://www.python.org/')
print('Version:', get_value(tag_key, 'Version') or tag[:3])
print('SysVersion:', get_value(tag_key, 'SysVersion') or tag[:3])
# Architecture is unknown because we are in HKCU
# Tools may use alternate approaches to determine architecture when
# the registration does not specify it.
print('SysArchitecture:', get_value(tag_key, 'SysArchitecture') or '(unknown)')
try:
ip_key = winreg.OpenKey(company_key, tag + '\\InstallPath')
except FileNotFoundError:
pass
else:
with ip_key:
ip = get_value(ip_key, None)
exe = get_value(ip_key, 'ExecutablePath') or os.path.join(ip, 'python.exe')
exew = get_value(ip_key, 'WindowedExecutablePath') or os.path.join(ip, 'python.exe')
print('InstallPath:', ip)
print('ExecutablePath:', exe)
print('WindowedExecutablePath:', exew)
print()
이 예제는 64비트 Python 3.6.0을 현재 사용자 전용으로 설치할 때 만들어지는 등록 정보의 일부를 보여 줍니다. 다른 키도 만들어질 수 있습니다:
HKEY_CURRENT_USER\Software\Python\PythonCore
(Default) = (value not set)
DisplayName = "Python Software Foundation"
SupportUrl = "http://www.python.org/"
HKEY_CURRENT_USER\Software\Python\PythonCore\3.6
(Default) = (value not set)
DisplayName = "Python 3.6 (64-bit)"
SupportUrl = "http://www.python.org/"
Version = "3.6.0"
SysVersion = "3.6"
SysArchitecture = "64bit"
HKEY_CURRENT_USER\Software\Python\PythonCore\3.6\Help\Main Python Documentation
(Default) = "C:\Users\Me\AppData\Local\Programs\Python\Python36\Doc\python360.chm"
DisplayName = "Python 3.6.0 Documentation"
HKEY_CURRENT_USER\Software\Python\PythonCore\3.6\InstallPath
(Default) = "C:\Users\Me\AppData\Local\Programs\Python\Python36\"
ExecutablePath = "C:\Users\Me\AppData\Local\Programs\Python\Python36\python.exe"
WindowedExecutablePath = "C:\Users\Me\AppData\Local\Programs\Python\Python36\pythonw.exe"
참고 문헌
Copyright
This document has been placed in the public domain.