languitar
languitar

Reputation: 6794

python: from x import y changes previous import result

I am trying to understand the package and module name shadowing rules in python and stumbled across a case where I do not understand why the results that I see make any sense. This cases happens for python 2 (with from future import absolute_imports) and python 3.

Assuming I have the following folder structure:

├── mypackage
│   ├── argparse.py
│   └── __init__.py
└── script.py

mypackage is my custom top-level package, where I have a module shadowing the standard argparse module. Inside my script I execute the following code:

import argparse
print(argparse)
from mypackage.argparse import foo
print(argparse)

The results are the ones I expect:

<module 'argparse' from '/usr/lib/python3.5/argparse.py'>
<module 'argparse' from '/usr/lib/python3.5/argparse.py'>

However, if I change my script to execute a function from my package and execute the same import and print statements in the __init__.py of my package, i.e.:

script:

from mypackage import main
main()

__init__.py:

import argparse
print(argparse)
from mypackage.argparse import foo
print(argparse)

def main():
    pass

As a result I see:

<module 'argparse' from '/usr/lib/python3.5/argparse.py'>
<module 'mypackage.argparse' from '/tmp/test/src/mypackage/argparse.py'>

Why does in this case (and not in the other one) the from X import Y statement override the previous global import of argparse to the local module?

Upvotes: 3

Views: 99

Answers (1)

Tadhg McDonald-Jensen
Tadhg McDonald-Jensen

Reputation: 21474

Consider how you access submodules, you would write mypackage.argparse to access the submodule of mypackage.

Now consider how attribute lookup for modules work, it searches for the attribute in the modules global namespace.

Putting these two together, the only way to access submodules is by adding them to the packages global namespace, this is the intended behaviour.

Upvotes: 1

Related Questions