Skip to content

from module import function creates package reference to the module #71730

Description

@mnijland
mannequin
BPO 27543
Nosy @brettcannon, @ncoghlan, @bitdancer, @ericsnowcurrently

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 = <Date 2016-07-18.02:36:15.029>
created_at = <Date 2016-07-17.18:14:01.041>
labels = ['interpreter-core', 'type-bug', 'invalid']
title = 'from module import function creates package reference to the module'
updated_at = <Date 2016-07-18.11:44:27.206>
user = 'https://bugs.python.org/mnijland'

bugs.python.org fields:

activity = <Date 2016-07-18.11:44:27.206>
actor = 'r.david.murray'
assignee = 'none'
closed = True
closed_date = <Date 2016-07-18.02:36:15.029>
closer = 'brett.cannon'
components = ['Interpreter Core']
creation = <Date 2016-07-17.18:14:01.041>
creator = 'm.nijland'
dependencies = []
files = []
hgrepos = []
issue_num = 27543
keywords = []
message_count = 5.0
messages = ['270658', '270668', '270671', '270676', '270748']
nosy_count = 5.0
nosy_names = ['brett.cannon', 'ncoghlan', 'r.david.murray', 'eric.snow', 'm.nijland']
pr_nums = []
priority = 'normal'
resolution = 'not a bug'
stage = None
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue27543'
versions = ['Python 2.7']

Activity

  1. mnijland commented on Jul 17, 2016

    mnijlandmannequin
    MannequinAuthor

    Hello,

    I've found an issue in python 2.7 and 3.4 and I don't if this is a bug or a feature that acts strange to me.

    The import of a module or method from a module creates a reference in the package to that module only the first time, which could lead to unexpected behavior.

    Description:
    In following code there's one line marked with 'this line fixes the code to what I expected'

    1. Without that line package.a.test() results in 'from module a'
    2. With the line package.a.test() results in 'from module b'

    Situation 1 is unexpected because I did not create the reference to 'module a', python did that with the statement 'from package.a import test' and this will happen from any place in the code that loads 'module a' for the first time. The documentation says that this reference will not be created.

    Kind regards,

    Marc

    # FILES USED

    # test.py
    # package
    # __init__.py
    # a.py
    # b.py
    # ---------------------
    # Content of a.py:

    def test():
        print('from module a')

    # ---------------------
    # Content of a.py:

    def test():
        print('from module b')

    # ---------------------
    # Content of __init__.py

    #import a # <--- this line fixes the code to what I expected
    import b as a
    from a import test

    # ---------------------
    # Content of test.py

    import package
    
    print(dir(package))
    package.a.test()
  2. added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    type-bugAn unexpected behavior, bug, or error
    on Jul 17, 2016
  3. brettcannon commented on Jul 17, 2016

    @brettcannon
    Member

    I'm not at a computer where I can verify what you're seeing, Marc,but I should mention that at least for Python 3 your imports are wrong as you should be doing relative imports, e.g. from . import b as a, otherwise the imports won't work unless you're accidentally executing Python from within the directory of the package.

  4. bitdancer commented on Jul 18, 2016

    @bitdancer
    Member

    The same example can be constructed for python3 by modifying the imports.

    I think what is happening here is that if a has not yet been imported, then when 'from .a import test' is done, the import machinery loads a and then defines 'a' in the local namespace, overriding the previous 'import package.b as a'. On the other hand, if a has already been imported, the import machinery finds 'a' in sys.modules and skips the import-and-set-name-in-local-namespace step.

    IMO the bug is that 'a' gets set at all when 'from a import test' is done, but the fact that it does so has a long history.

  5. brettcannon commented on Jul 18, 2016

    @brettcannon
    Member

    So the problem is that you doing from .a import test and not from . import a; test = a.test. Whenever you do from X import Y, import actually imports X. Since X wasn't in sys.modules, it performs a proper import which means it sets the attribute on the package accordingly. But had Y been what you were after, then import simply looks for the Y attribute on the package instead of doing a full import.

    IOW everything is working as expected (and I still wish people weren't allowed to import objects out of modules directly).

  6. bitdancer commented on Jul 18, 2016

    @bitdancer
    Member

    Note that conceptually this is closely related to bpo-27515. In both cases the conceptual problem (the thing that trips up user expectations) is that what import does to the namespaces differs depending on whether the base module exists in sys.modules or not. I don't know that there is a fix, but it is certainly an inconsistency that causes mental hiccoughs.

  7. transferred this issue fromon Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions