Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

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

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 타사 설치 관리자가 자신의 설치를 등록하고, 도구와 애플리케이션이 사용자 컴퓨터의 모든 Python 환경을 감지하여 올바르게 표시할 수 있도록 Python 레지스트리 키의 스키마를 정의합니다. 이 PEP에서는 Python의 구현 변경을 제안하지 않습니다.

외부 도구에서 자동으로 검색되기를 원하는 경우가 아니라면 Python 환경을 등록할 필요가 없습니다. 이는 Windows에만 해당하므로 이러한 도구는 대부분 GUI 애플리케이션일 것으로 예상됩니다. 그러나 콘솔 애플리케이션도 등록된 정보를 사용할 수 있습니다. 이 PEP는 제공될 수 있는 정보를 다루지만, 이 정보의 실제 표시와 사용은 도구 설계자에게 맡깁니다.

스키마는 적어도 Python 2.5 이후 공식 설치 관리자가 사용해 온 레지스트리 값과 일치하며, 해석 동작은 공식 Python 릴리스의 동작과 일치합니다. 전체 정보를 등록하지 않는 CPython 버전을 도구가 올바르게 감지할 수 있도록 일부 하위 호환성 규칙이 제공됩니다.

동기

Windows에 설치되면 공식 Python 설치 관리자가 다른 애플리케이션에서 검색하고 감지할 수 있도록 레지스트리 키를 생성합니다. 이를 통해 설치 관리자나 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 Library [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 쌍이 일치하는 경우에도 해당 환경을 포함하도록 선택할 수 있습니다. 사용자가 등록이 사용자별인지 컴퓨터별인지, 그리고 어느 등록의 우선순위가 더 높은지를 쉽게 식별할 수 있도록 해야 합니다.

Company-Tag 쌍을 기준으로 등록된 모든 환경 중 하나의 설치된 환경을 선택하려는 도구(예: py.exe 런처)는 항상 HKEY_LOCAL_MACHINE에서 일치하는 환경 대신 HKEY_CURRENT_USER에 등록된 환경을 선택해야 합니다.

HKEY_LOCAL_MACHINE\Software\PythonHKEY_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비트인지 판단하여 컴퓨터별 환경보다 우선하도록 할 수 있으며, 그 결과 검색되는 환경은 최대 두 개가 됩니다.

Python 3.5 이전 버전의 64비트 버전과 32비트 버전이 현재 사용자용으로 설치된 경우, 두 버전의 나란히 설치를 감지할 수 없습니다. Python 3.5 이상에서는 64비트 버전과 32비트 버전에 항상 서로 다른 Tag를 사용합니다.

다음 절에서는 등록될 수 있는 사용자에게 표시되는 정보를 설명합니다. Python 3.5 이하에서는 이 정보 중 어느 것도 사용할 수 없지만, PythonCore키에 대한 대체 기본값이 지정되어 있습니다.

다른 Company 이름으로 등록된 환경에는 하위 호환성 요구 사항이 없으며, 나란히 설치를 지원하려면 서로 다른 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

회사 이름 PyLauncherPEP 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의 기본값은 Tag 앞에 “Python “을 붙인 값입니다.)

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"

참고 자료