This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: PEP 499 implementation: "python -m foo" binds the main module as both __main__ and foo in sys.modules
Type: enhancement Stage: patch review
Components: Interpreter Core Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Greg Price, cameron, eric.snow, ncoghlan
Priority: normal Keywords: patch

Created on 2019-03-20 00:14 by cameron, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 12455 closed cameron, 2019-03-20 00:28
PR 12490 open cameron, 2019-03-22 02:27
Messages (10)
msg338425 - (view) Author: Cameron Simpson (cameron) * Date: 2019-03-20 00:14
This issue is to track the implementation of PEP 499 which we hope to get into the upcoming 3.8 release. I've made it because cpython PRs want a bpo number in the subject line.

I'll link in the proposed PR once I've filed off a few grammar issues I've just noticed (documentation English grammar).
msg338526 - (view) Author: Cameron Simpson (cameron) * Date: 2019-03-21 05:30
I've withdrawn the PR; I hadn't run the full test suite and there are things to fix. - Cameron
msg338579 - (view) Author: Cameron Simpson (cameron) * Date: 2019-03-22 02:30
New PR 12490 attached with a fix for test_pdb. More extensive comments are in the leading comment on the PR itself. - Cameron
msg356499 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2019-11-12 22:37
[Belatedly updating this issue with the current status as of March]

Cameron's implementation generally looks good, but there are couple of compatibility/migration questions that we need to consider, as spelled out in the PEP update that added me as BDFL-Delegate: https://github.com/python/peps/pull/946/files

* We need a generic porting guide entry to handle projects that turn out to have been relying on their name *not* being bound in sys.modules. For example, adding this preamble:

    if __name__ == "__main__":
        # To prevent inadvertent double imports, the -m
        # switch in Python 3.9+ defaults to aliasing __main__
        # under the executed module's import name. We actually
        # want the double import, so remove the alias if it exists
        import sys
        _main_module = sys.modules.get(__name__)
        _spec_module = sys.modules.get(__spec__.name)
        if _main_module is _spec_module:
            sys.modules.pop(__spec__.name)

We'd test the above snippet by adding it to the `pdb` module (and reverting the other compatibility changes to that module)

* We need to understand the implications for pickle compatibility, and provide a porting guide snippet, similar to the one above for explicitly requesting the double-import behaviour. For example:

    if __name__ == "__main__":
        # To prevent inadvertent double imports, the -m
        # switch in Python 3.9+ defaults to aliasing __main__
        # under the executed module's import name. We need
        # pickle to use the real module name for objects from
        # __main__ though, so we set the import name here
        _running_as_main = True
        __name__ = __spec__.name
msg356509 - (view) Author: Cameron Simpson (cameron) * Date: 2019-11-13 00:32
I want to start with an apology. I have become a little swamped by work and didn't let anyone know I've made little time for this since March.

To my naive eye Nick's snippet looks like it would work for pdb; I became a little stalled there trying to understand how pdb managed the main module.

I totally lack the expertise to address pickle; I've never used it and the long history of feature updates sugests to me that I cannot get a deep enough understanding in a meaningful time.
msg356515 - (view) Author: Cameron Simpson (cameron) * Date: 2019-11-13 05:07
Just a remark about the preamble comment: it reads to me as though PEP499 is a misfeature. Possibly change:

  We actually want the double import, so remove the alias if it exists.

to:

  This module is unusual, and actually wants the double import.
  Therefore we remove the __spec__.name alias if it exists
  so that a subsequent import by name will make a distinct instance.

Verbose, but at least I know the intent.
msg357449 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2019-11-25 17:38
FWIW, I have some feedback on the PEP.  (See msg357448.)  Can we discuss here or should I open a mailing list thread?
msg357478 - (view) Author: Cameron Simpson (cameron) * Date: 2019-11-26 03:59
On 25Nov2019 17:38, Python Bug Reports <report@bugs.python.org> wrote:
>Eric Snow <ericsnowcurrently@gmail.com> added the comment:
>
>FWIW, I have some feedback on the PEP.  (See msg357448.)  Can we discuss here or should I open a mailing list thread?

Let's discuss it here unless it looks like we need wider input. This is 
related to issue37292 (_xxsubinterpreters: Can't unpickle objects 
defined in __main__), yes?

With PEP499, "python -m foo" should have __name__=='__main__' and 
__spec__.name=='foo'. Were you thinking the __module__ should come from 
__spec__.name (and that the PEP should make that clear)?
msg357503 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2019-11-26 15:32
Exactly. :)

I'd expect PEP 499 to specify changing __module__ of classes and functions from __main__ to the module name (__spec__.name).  This aligns closely with the whole point of the PEP. :)  As a bonus, it will simplify things for pickling (which doesn't inherently deal well with __main__).
msg358421 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2019-12-15 12:35
Leaving the relationship between pickle and __name__ alone wasn't an oversight, as folks already rely on that to gracefully transition from single-file modules to multi-file packages without breaking pickle compatibility in either direction. The trick is to do a "from ._submodule import *" in the package's __init__.py (exposing all the names), and then a "__name__ = __package__" in the submodule itself.

Thus the second snippet above, as a way to port code that was specifically relying on the double import to provide pickle compatibility without risking introducing other unintended incompatibility problems.
History
Date User Action Args
2022-04-11 14:59:12adminsetgithub: 80556
2019-12-15 12:35:30ncoghlansetmessages: + msg358421
2019-11-26 15:32:01eric.snowsetmessages: + msg357503
2019-11-26 03:59:28cameronsetmessages: + msg357478
2019-11-25 17:38:12eric.snowsetnosy: + eric.snow
messages: + msg357449
2019-11-13 05:07:53cameronsetmessages: + msg356515
2019-11-13 00:32:41cameronsetmessages: + msg356509
2019-11-12 22:37:59ncoghlansetmessages: + msg356499
2019-08-21 19:42:29Greg Pricesetnosy: + Greg Price
2019-03-22 02:30:19cameronsetmessages: + msg338579
2019-03-22 02:27:46cameronsetpull_requests: + pull_request12442
2019-03-21 05:30:36cameronsetmessages: + msg338526
2019-03-20 00:28:56cameronsetkeywords: + patch
stage: patch review
pull_requests: + pull_request12408
2019-03-20 00:14:00cameroncreate