Use "import a.b" but a.b may not be what I want, even not a module (Issue #117314)

When I use import a.b and print (a.b), the result may not be what I want, if I import something from b and rename it to b in the __ init__. py of a

The content after # is the output of test.py

#b.py/c.py
x=type("x",(),{})

# __init__py
# from .b import x as b  # bug <class 'a.b.x'>
# from a.b import x as b  # bug <class 'a.b.x'>
# But when I use“from folder.a.b import x as b" in PyCharm, it is normal <module 'a.b' from ‘***’>
# from .c import x as b  # normal <module 'a.b' from ‘***’>
# b=type("b",(),{})  # normal <module 'a.b' from ‘***’>

# test.py
import a.b
print (a.b)

I think when I successfully “import a.b” (without raise a ModuleNotFoundError), it should have found the “a.b” module rather than anything else.

By the way, when I use from a import b and print (b), the result is:

#b.py/c.py
x=type("x",(),{})

# __init__py
# from .b import x as b  # <class 'a.b.x'>
# from a.b import x as b  # <class 'a.b.x'>
# from .c import x as b  # <class  'a.c.x'>
# b=type("b",(),{})  # <class 'a.b'>

# test.py
import a.b
print (a.b)

It is normal.
The file structure is as follows:

folder
-test.py
-a
--__init__.py
--b.py
--c.py

Even if not renamed, it will still occur

#b.py/c.py
b=type("b",(),{})

# __init__py
from .b import b # <class 'a.b.b'>

# test.py
import a.b
print (a.b)

Try the following:

import some_module as new_name
alternate_name = new_name

# Question for you: what is not "the" name of some_module?

print(new_name)
print(alternate_name)
print(new_name.__repr__())
print(alternate_name.__repr__())
print(new_name.__str__())
print(new_name.__name__)
# etc

Inside a module, you can assign one or more names to any object so that you can use them as local synonyms for that object. However, the object identity has not changed because of the synonym that you defined for them and use to refer to them in your own module.

1 Like

Thank you very much for your answer. I apologize for any inconvenience caused by my unclear question. Now I have tried to change my description:
The content after # is the output of test.py

import can be confusing.

The key point here is that

import a.b

means import a to the interpreter, if necessary, then look for b in the dictionary of the a package. It isn’t primarily an operation on files.

When a is imported into the interpreter, and after b and c have been imported and added to it, you get to manipulate the dictionary as __init__.py executes. If you change the meaning of b, then that’s what a.b means by the time anyone looks.

2 Likes

Thank you for your inspiration.
But in the case of the same name, the module seems to be more than just a separate dictionary.
Please see the example below:

### The content after #  still is the output of test.py
#a/__init__.py
b=type("b",(),{})

#test.py
import a # <class 'a.b'>
# import a.b # <module 'a.b'>
print(a.b)

And I found that when I import b in __ init__. py, even if I del b, the program did not perform the import operation again.This is the reason why this phenomenon occurs.

A module is more than just a dictionary, but almost all we can see of it from another module is its dictionary.

It’s important to understand that a module body is executed once, when it is imported into the interpreter. It may be imported many times into other modules, but that is at most adding it to that module’s dictionary.

2 Likes