[Python-Dev] PEP 514: Python registration in the Windows registry

Steve Dower steve.dower at python.org
Sun Jul 24 14:29:14 EDT 2016


Thanks Paul.

I'll update the headers on the PEP later today.

Top-posted from my Windows Phone

-----Original Message-----
From: "Paul Moore" <p.f.moore at gmail.com>
Sent: ‎7/‎24/‎2016 0:45
To: "Guido van Rossum" <guido at python.org>
Cc: "Steve Dower" <steve.dower at python.org>; "Python Dev" <python-dev at python.org>
Subject: Re: [Python-Dev] PEP 514: Python registration in the Windows registry

This PEP is now accepted. Congratulations, Steve! And thanks for
putting up with all of my last-minute questions :-)

Paul

On 23 July 2016 at 21:20, Guido van Rossum <guido at python.org> wrote:
> I'll let Paul pronounce. But you should probably have a BDFL-Delegate:
> ... header.
>
> On Sat, Jul 23, 2016 at 12:16 PM, Steve Dower <steve.dower at python.org> wrote:
>> PEP 514 is now ready for pronouncement, so this is the last chance for any
>> feedback (BDFL-delegate Paul has been active on the github PR, so I don't
>> expect he has a lot of feedback left).
>>
>> The most major change from the previous post is the addition of some code
>> examples at the end. Honestly, I don't expect many tools written in Python
>> to be scanning the registry (since once you're in Python you probably don't
>> need to find it), but hopefully they'll help clarify the PEP for people who
>> prefer code.
>>
>> Full text below.
>>
>> Cheers,
>> Steve
>>
>> ----------
>>
>> PEP: 514
>> Title: Python registration in the Windows registry
>> Version: $Revision$
>> Last-Modified: $Date$
>> Author: Steve Dower <steve.dower at python.org>
>> Status: Draft
>> Type: Informational
>> Content-Type: text/x-rst
>> Created: 02-Feb-2016
>> Post-History: 02-Feb-2016, 01-Mar-2016, 18-Jul-2016
>>
>> Abstract
>> ========
>>
>> This PEP defines a schema for the Python registry key to allow third-party
>> installers to register their installation, and to allow tools and
>> applications
>> to detect and correctly display all Python environments on a user's machine.
>> No
>> implementation changes to Python are proposed with this PEP.
>>
>> Python environments are not required to be registered unless they want to be
>> automatically discoverable by external tools. As this relates to Windows
>> only,
>> these tools are expected to be predominantly GUI applications. However,
>> console
>> applications may also make use of the registered information. This PEP
>> covers
>> the information that may be made available, but the actual presentation and
>> use
>> of this information is left to the tool designers.
>>
>> The schema matches the registry values that have been used by the official
>> installer since at least Python 2.5, and the resolution behaviour matches
>> the
>> behaviour of the official Python releases. Some backwards compatibility
>> rules
>> are provided to ensure tools can correctly detect versions of CPython that
>> do
>> not register full information.
>>
>> Motivation
>> ==========
>>
>> When installed on Windows, the official Python installer creates a registry
>> key
>> for discovery and detection by other applications. This allows tools such as
>> installers or IDEs to automatically detect and display a user's Python
>> installations. For example, the PEP 397 ``py.exe`` launcher and editors such
>> as
>> PyCharm and Visual Studio already make use of this information.
>>
>> Third-party installers, such as those used by distributions, typically
>> create
>> identical keys for the same purpose. Most tools that use the registry to
>> detect
>> Python installations only inspect the keys used by the official installer.
>> As a
>> result, third-party installations that wish to be discoverable will
>> overwrite
>> these values, often causing users to "lose" their original Python
>> installation.
>>
>> By describing a layout for registry keys that allows third-party
>> installations
>> to register themselves uniquely, as well as providing tool developers
>> guidance
>> for discovering all available Python installations, these collisions should
>> be
>> prevented. We also take the opportunity to add some well-known metadata so
>> that
>> more information can be presented to users.
>>
>> Definitions
>> ===========
>>
>> A "registry key" is the equivalent of a file-system path into the registry.
>> Each
>> key may contain "subkeys" (keys nested within keys) and "values" (named and
>> typed attributes attached to a key). These are used on Windows to store
>> settings
>> in much the same way that directories containing configuration files would
>> work.
>>
>> ``HKEY_CURRENT_USER`` is the root of settings for the currently logged-in
>> user,
>> and this user can generally read and write all settings under this root.
>>
>> ``HKEY_LOCAL_MACHINE`` is the root of settings for all users. Generally, any
>> user can read these settings but only administrators can modify them. It is
>> typical for values under ``HKEY_CURRENT_USER`` to take precedence over those
>> in
>> ``HKEY_LOCAL_MACHINE``.
>>
>> On 64-bit Windows, ``HKEY_LOCAL_MACHINE\Software\Wow6432Node`` is a special
>> key
>> that 32-bit processes transparently read and write to rather than accessing
>> the
>> ``Software`` key directly.
>>
>> Further documentation regarding registry redirection on Windows is available
>> from the MSDN Library [1]_.
>>
>> Structure
>> =========
>>
>> We consider there to be a single collection of Python environments on a
>> machine,
>> where the collection may be different for each user of the machine. There
>> are
>> three potential registry locations where the collection may be stored based
>> on
>> the installation options of each environment::
>>
>>     HKEY_CURRENT_USER\Software\Python\<Company>\<Tag>
>>     HKEY_LOCAL_MACHINE\Software\Python\<Company>\<Tag>
>>     HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\<Company>\<Tag>
>>
>> Official Python releases use ``PythonCore`` for Company, and the value of
>> ``sys.winver`` for Tag. The Company ``PyLauncher`` is reserved. Other
>> registered
>> environments may use any values for Company and Tag. Recommendations are
>> made
>> later in this document.
>>
>> Company-Tag pairs are case-insensitive, and uniquely identify each
>> environment.
>> Depending on the purpose and intended use of a tool, there are two suggested
>> approaches for resolving conflicts between Company-Tag pairs.
>>
>> Tools that list every installed environment may choose to include those
>> even where the Company-Tag pairs match. They should ensure users can easily
>> identify whether the registration was per-user or per-machine, and which
>> registration has the higher priority.
>>
>> Tools that aim to select a single installed environment from all registered
>> environments based on the Company-Tag pair, such as the ``py.exe`` launcher,
>> should always select the environment registered in ``HKEY_CURRENT_USER``
>> when
>> than the matching one in ``HKEY_LOCAL_MACHINE``.
>>
>> Conflicts between ``HKEY_LOCAL_MACHINE\Software\Python`` and
>> ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python`` should only occur when
>> both
>> 64-bit and 32-bit versions of an interpreter have the same Tag. In this
>> case,
>> the tool should select whichever is more appropriate for its use.
>>
>> If a tool is able to determine from the provided information (or lack
>> thereof)
>> that it cannot use a registered environment, there is no obligation to
>> present
>> it to users.
>>
>> Except as discussed in the section on backwards compatibility, Company and
>> Tag
>> values are considered opaque to tools, and no information about the
>> interpreter
>> should be inferred from the text. However, some tools may display the
>> Company
>> and Tag values to users, so ideally the Tag will be able to help users
>> identify
>> the associated environment.
>>
>> Python environments are not required to register themselves unless they want
>> to
>> be automatically discoverable by external tools.
>>
>> Backwards Compatibility
>> -----------------------
>>
>> Python 3.4 and earlier did not distinguish between 32-bit and 64-bit builds
>> in
>> ``sys.winver``. As a result, it is not possible to have valid side-by-side
>> installations of both 32-bit and 64-bit interpreters under this scheme since
>> it
>> would result in duplicate Tags.
>>
>> To ensure backwards compatibility, applications should treat environments
>> listed
>> under the following two registry keys as distinct, even when the Tag
>> matches::
>>
>>     HKEY_LOCAL_MACHINE\Software\Python\PythonCore\<Tag>
>>     HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\PythonCore\<Tag>
>>
>> Environments listed under ``HKEY_CURRENT_USER`` may be treated as distinct
>> from
>> both of the above keys, potentially resulting in three environments
>> discovered
>> using the same Tag. Alternatively, a tool may determine whether the per-user
>> environment is 64-bit or 32-bit and give it priority over the per-machine
>> environment, resulting in a maximum of two discovered environments.
>>
>> It is not possible to detect side-by-side installations of both 64-bit and
>> 32-bit versions of Python prior to 3.5 when they have been installed for the
>> current user. Python 3.5 and later always uses different Tags for 64-bit and
>> 32-bit versions.
>>
>> The following section describe user-visible information that may be
>> registered.
>> For Python 3.5 and earlier, none of this information is available, but
>> alternative defaults are specified for the ``PythonCore`` key.
>>
>> Environments registered under other Company names have no backward
>> compatibility
>> requirements and must use distinct Tags to support side-by-side
>> installations.
>> Tools consuming these registrations are not required to disambiguate tags
>> other
>> than by preferring the user's setting.
>>
>> Company
>> -------
>>
>> The Company part of the key is intended to group related environments and to
>> ensure that Tags are namespaced appropriately. The key name should be
>> alphanumeric without spaces and likely to be unique. For example, a
>> trademarked
>> name (preferred), a hostname, or as a last resort, a UUID would be
>> appropriate::
>>
>>     HKEY_CURRENT_USER\Software\Python\ExampleCorp
>>     HKEY_CURRENT_USER\Software\Python\www.example.com
>>     HKEY_CURRENT_USER\Software\Python\6C465E66-5A8C-4942-9E6A-D29159480C60
>>
>> The company name ``PyLauncher`` is reserved for the PEP 397 launcher
>> (``py.exe``). It does not follow this convention and should be ignored by
>> tools.
>>
>> If a string value named ``DisplayName`` exists, it should be used to
>> identify
>> the environment manufacturer/developer/destributor to users. Otherwise, the
>> name
>> of the key should be used. (For ``PythonCore``, the default display name is
>> "Python Software Foundation".)
>>
>> If a string value named ``SupportUrl`` exists, it may be displayed or
>> otherwise
>> used to direct users to a web site related to the environment. (For
>> ``PythonCore``, the default support URL is "http://www.python.org/".)
>>
>> A complete example may look like::
>>
>>     HKEY_CURRENT_USER\Software\Python\ExampleCorp
>>         (Default) = (value not set)
>>         DisplayName = "Example Corp"
>>         SupportUrl = "http://www.example.com"
>>
>> Tag
>> ---
>>
>> The Tag part of the key is intended to uniquely identify an environment
>> within
>> those provided by a single company. The key name should be alphanumeric
>> without
>> spaces and stable across installations. For example, the Python language
>> version, a UUID or a partial/complete hash would be appropriate, while a Tag
>> based on the install directory or some aspect of the current machine may
>> not.
>> For example::
>>
>>     HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy
>>     HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6
>>     HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66
>>
>> It is expected that some tools will require users to type the Tag into a
>> command
>> line, and that the Company may be optional provided the Tag is unique across
>> all
>> Python installations. Short, human-readable and easy to type Tags are
>> recommended, and if possible, select a value likely to be unique across all
>> other Companies.
>>
>> If a string value named ``DisplayName`` exists, it should be used to
>> identify
>> the environment to users. Otherwise, the name of the key should be used.
>> (For
>> ``PythonCore``, the default is "Python " followed by the Tag.)
>>
>> If a string value named ``SupportUrl`` exists, it may be displayed or
>> otherwise
>> used to direct users to a web site related to the environment. (For
>> ``PythonCore``, the default is "http://www.python.org/".)
>>
>> If a string value named ``Version`` exists, it should be used to identify
>> the
>> version of the environment. This is independent from the version of Python
>> implemented by the environment. (For ``PythonCore``, the default is the
>> first
>> three characters of the Tag.)
>>
>> If a string value named ``SysVersion`` exists, it must be in ``x.y`` or
>> ``x.y.z`` format matching the version returned by ``sys.version_info`` in
>> the
>> interpreter. If omitted, the Python version is unknown. (For ``PythonCore``,
>> the default is the first three characters of the Tag.)
>>
>> If a string value named ``SysArchitecture`` exists, it must match the first
>> element of the tuple returned by ``platform.architecture()``. Typically,
>> this
>> will be "32bit" or "64bit". If omitted, the architecture is unknown. (For
>> ``PythonCore``, the architecture is "32bit" when registered under
>> ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python`` *or* anywhere on a 32-bit
>> operating system, "64bit" when registered under
>> ``HKEY_LOCAL_MACHINE\Software\Python`` on a 64-bit machine, and unknown when
>> registered under ``HKEY_CURRENT_USER``.)
>>
>> Note that each of these values is recommended, but optional. Omitting
>> ``SysVersion`` or ``SysArchitecture`` may prevent some tools from correctly
>> supporting the environment. A complete example may look like this::
>>
>>     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
>> -----------
>>
>> Beneath the environment key, an ``InstallPath`` key must be created. This
>> key is
>> always named ``InstallPath``, and the default value must match
>> ``sys.prefix``::
>>
>>     HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6\InstallPath
>>         (Default) = "C:\ExampleCorpPy36"
>>
>> If a string value named ``ExecutablePath`` exists, it must be the full path
>> to
>> the ``python.exe`` (or equivalent) executable. If omitted, the environment
>> is
>> not executable. (For ``PythonCore``, the default is the ``python.exe`` file
>> in
>> the directory referenced by the ``(Default)`` value.)
>>
>> If a string value named ``ExecutableArguments`` exists, tools should use the
>> value as the first arguments when executing ``ExecutablePath``. Tools may
>> add
>> other arguments following these, and will reasonably expect standard Python
>> command line options to be available.
>>
>> If a string value named ``WindowedExecutablePath`` exists, it must be a path
>> to
>> the ``pythonw.exe`` (or equivalent) executable. If omitted, the default is
>> the
>> value of ``ExecutablePath``, and if that is omitted the environment is not
>> executable. (For ``PythonCore``, the default is the ``pythonw.exe`` file in
>> the
>> directory referenced by the ``(Default)`` value.)
>>
>> If a string value named ``WindowedExecutableArguments`` exists, tools should
>> use
>> the value as the first arguments when executing ``WindowedExecutablePath``.
>> Tools may add other arguments following these, and will reasonably expect
>> standard Python command line options to be available.
>>
>> A complete example may look like::
>>
>>     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
>> ----
>>
>> Beneath the environment key, a ``Help`` key may be created. This key is
>> always
>> named ``Help`` if present and has no default value.
>>
>> Each subkey of ``Help`` specifies a documentation file, tool, or URL
>> associated
>> with the environment. The subkey may have any name, and the default value is
>> a
>> string appropriate for passing to ``os.startfile`` or equivalent.
>>
>> If a string value named ``DisplayName`` exists, it should be used to
>> identify
>> the help file to users. Otherwise, the key name should be used.
>>
>> A complete example may look like::
>>
>>     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"
>>
>> Other Keys
>> ----------
>>
>> All other subkeys under a Company-Tag pair are available for private use.
>>
>> Official CPython releases have traditionally used certain keys in this space
>> to
>> determine the location of the Python standard library and other installed
>> modules. This behaviour is retained primarily for backward compatibility.
>> However, as the code that reads these values is embedded into the
>> interpreter,
>> third-party distributions may be affected by values written into
>> ``PythonCore``
>> if using an unmodified interpreter.
>>
>> Sample Code
>> ===========
>>
>> This sample code enumerates the registry and displays the available
>> Company-Tag
>> pairs that could be used to launch an environment and the target executable.
>> It
>> only shows the most-preferred target for the tag. Backwards-compatible
>> handling
>> of ``PythonCore`` is omitted but shown in a later example::
>>
>>     # 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 comany 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 ex


[The entire original message is not included.]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20160724/9ddd990d/attachment-0001.html>


More information about the Python-Dev mailing list