Skip to content

PEP 499 implementation: "python -m foo" binds the main module as both __main__ and foo in sys.modules #80556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cameron-simpson mannequin opened this issue Mar 20, 2019 · 11 comments
Labels
3.8 (EOL) end of life interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-importlib type-feature A feature request or enhancement

Comments

@cameron-simpson
Copy link
Mannequin

cameron-simpson mannequin commented Mar 20, 2019

BPO 36375
Nosy @ncoghlan, @cameron-simpson, @ericsnowcurrently, @gnprice
PRs
  • bpo-36375: PEP499: implementation and documentation and test updates #12455
  • bpo-36375: PEP 499 implementation: "python -m foo" binds the main module as both __main__ and foo in sys.modules #12490
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2019-03-20.00:14:00.405>
    labels = ['interpreter-core', 'type-feature', '3.8']
    title = 'PEP 499 implementation: "python -m foo" binds the main module as both __main__ and foo in sys.modules'
    updated_at = <Date 2019-12-15.12:35:30.830>
    user = 'https://github.com/cameron-simpson'

    bugs.python.org fields:

    activity = <Date 2019-12-15.12:35:30.830>
    actor = 'ncoghlan'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Interpreter Core']
    creation = <Date 2019-03-20.00:14:00.405>
    creator = 'cameron'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 36375
    keywords = ['patch']
    message_count = 10.0
    messages = ['338425', '338526', '338579', '356499', '356509', '356515', '357449', '357478', '357503', '358421']
    nosy_count = 4.0
    nosy_names = ['ncoghlan', 'cameron', 'eric.snow', 'Greg Price']
    pr_nums = ['12455', '12490']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue36375'
    versions = ['Python 3.8']

    @cameron-simpson
    Copy link
    Mannequin Author

    cameron-simpson mannequin commented Mar 20, 2019

    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).

    @cameron-simpson cameron-simpson mannequin added 3.8 (EOL) end of life interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement labels Mar 20, 2019
    @cameron-simpson
    Copy link
    Mannequin Author

    cameron-simpson mannequin commented Mar 21, 2019

    I've withdrawn the PR; I hadn't run the full test suite and there are things to fix. - Cameron

    @cameron-simpson
    Copy link
    Mannequin Author

    cameron-simpson mannequin commented Mar 22, 2019

    New PR 12490 attached with a fix for test_pdb. More extensive comments are in the leading comment on the PR itself. - Cameron

    @ncoghlan
    Copy link
    Contributor

    [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

    @cameron-simpson
    Copy link
    Mannequin Author

    cameron-simpson mannequin commented Nov 13, 2019

    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.

    @cameron-simpson
    Copy link
    Mannequin Author

    cameron-simpson mannequin commented Nov 13, 2019

    Just a remark about the preamble comment: it reads to me as though PEP-499 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.

    @ericsnowcurrently
    Copy link
    Member

    FWIW, I have some feedback on the PEP. (See msg357448.) Can we discuss here or should I open a mailing list thread?

    @cameron-simpson
    Copy link
    Mannequin Author

    cameron-simpson mannequin commented Nov 26, 2019

    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 bpo-37292 (xxsubinterpreters: Can't unpickle objects
    defined in __main
    _), yes?

    With PEP-499, "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)?

    @ericsnowcurrently
    Copy link
    Member

    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__).

    @ncoghlan
    Copy link
    Contributor

    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.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @erlend-aasland
    Copy link
    Contributor

    Suggesting to close this together with the linked PR, as PEP-499 is still not accepted. The issue and the patch can be revived if PEP-499 is accepted.

    @erlend-aasland erlend-aasland added the pending The issue will be closed if no feedback is provided label Jul 24, 2022
    @kumaraditya303 kumaraditya303 closed this as not planned Won't fix, can't repro, duplicate, stale Sep 6, 2022
    @erlend-aasland erlend-aasland removed the pending The issue will be closed if no feedback is provided label Sep 6, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.8 (EOL) end of life interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-importlib type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    5 participants