PEP 499: add some examples and other updates (#939)

* add some examples
* specify that packages are not affected by this change
* specify that use of module.__name__ should be replaced by module.__spec__.name where the canonical monudle name is required
* other small changes

[Unlike the original PR, this does *not* change Cameron's email. A separate PR is needed.]
This commit is contained in:
Cameron SImpson 2019-03-20 06:10:14 +11:00 committed by Guido van Rossum
parent e6fb1bcc32
commit ccdbb66ee4
1 changed files with 74 additions and 3 deletions

View File

@ -2,12 +2,12 @@ PEP: 499
Title: ``python -m foo`` should bind ``sys.modules['foo']`` in addition to ``sys.modules['__main__']``
Version: $Revision$
Last-Modified: $Date$
Author: Cameron Simpson <cs@zip.com.au>
Author: Cameron Simpson <cs@zip.com.au>, Chris Angelico <rosuav@gmail.com>, Joseph Jevnik <joejev@gmail.com>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 07-Aug-2015
Python-Version: 3.6
Python-Version: 3.8
Abstract
========
@ -38,8 +38,46 @@ then it will obtain the same module instance.
That actuality is that the module was imported only as ``'__main__'``.
Another import will obtain a distinct module instance, which can
lead to confusing bugs.
lead to confusing bugs,
all stemming from having two instances of module global objects:
one in each module.
Examples include:
module level data structures
Some modules provide features such as caches or registries
as module level global variables,
typically private.
A second instance of a module creates a second data structure.
If that structure is a cache
such as in the ``re`` module
then two caches exist leading to wasteful memory use.
If that structure is a shared registry
such as a mapping of values to handlers
then it is possible to register a handler to one registry
and to try to use it via the other registry, where it is unknown.
sentinels
The standard test for a sentinel value provided by a module
is the identity comparison using ``is``,
as this avoids unreliable "looks like" comparisons
such as equality which can both mismatch two values as "equal"
(for example being zeroish)
or raise a ``TypeError`` when the objects are incompatible.
When there are two instances of a module
there are two sentinel instances
and only one will be recognised via ``is``.
classes
With two modules
there are duplicate class definitions of any classes provided.
All operations which depend on recognising these classes
and subclasses of these are prone to failure
depending where the reference class
(from one of the modules) is obtained
and where the comparison class or instance is obtained.
This impacts ``isinstance``, ``issubclass``
and also ``try``/``except`` constructs.
Proposal
========
@ -60,6 +98,13 @@ to instead be::
sys.modules[mod_spec.name] = main_module
main_globals = main_module.__dict__
Joseph Jevnik has pointed out that modules which are packages already
do something very similar to this proposal:
the __init__.py file is bound to the module's canonical name
and the __main__.py file is bound to "__main__".
As such, the double import issue does not occur.
Therefore this PEP proposes to affect only simple non-package modules.
Considerations and Prerequisites
================================
@ -81,6 +126,32 @@ Nick has mentioned `issue 19702`_ which proposes (quoted from the issue):
The first point above covers this PEP's specific proposal.
A Normal Module's ``__name__`` Is No Longer Canonical
-----------------------------------------------------
Chris Angelico points out that it becomes possible to import a
module whose ``__name__`` is not what you gave to "import", since
"__main__" is now present at "module.name", so a subsequent
``import module.name`` finds it already present.
Therefore ``__name__`` is no longer the canonical name for some normal imports.
Some counter arguments follow:
- As of PEP 451 a module's canonical name is stored at ``__spec__.name``.
- Very little code should actually care about ``__name__`` being the canonical name
and any that does should arguably be updated to consult ``__spec__.name``
with fallback to ``__name__`` for older Pythons, should that be relevant.
This is true even if this PEP is not approved.
- Should this PEP be approved,
it becomes possible to introspect a module by its canonical name
and ask "was this the main program?" by inferring from ``__name__``.
This was not previously possible.
The glaring counter example is the standard "am I the main program?" boilerplate,
where ``__name__`` is expected to be "__main__".
This PEP explicitly preserves that semantic.
Background
==========