Python: "import ... as" causes incorrect reference

12,146

Solution 1

Why do you expect it to work? All 4 of your import statements are assignments to the variable a. Thus if you assign c to a, it overwrites the contents with something that doesn't have a .b attribute.


Here's what happens in the first case:

  1. When import a.b is run, Python loads module a, and then loads the module a.b into the loaded a module's attribute b. It then assigns the result to the variable a.
  2. The import a doesn't import anything new, because module a is already loaded. It simply reassigns the same module from sys.modules['a'] to a.

Here's what happens in the second case:

  1. When import a.b is run, Python loads module a, and then loads the module a.b into the loaded a module's attribute b. It then assigns the result to the variable a.
  2. When import c as a is run, it loads the module c, and then assigns that module to variable a, overwriting the contents (a = sys.modules['c']). You could verify this by comparing the contents of sys.modules['a'] with the contents of a - they'll be different in this case.

Solution 2

if you import c as a

it will overwrite your previous a

so if you try to call a.b you really call c.b

Solution 3

In the first case, a refers to the actual package a (which contains the module b). This means that a.b refers to something which is contained by a.

In the second case, a refers to module c.py. It's as though you tried import c; a = c. Now, if c doesn't have an attribute b, it will fail.

Solution 4

When you do an "import as" statement, you are really doing an assignment. So if you do this

import matplotlib as mp

you are assigning the namespace for matplotlib to mp.

That carries all of the usual implications of assignment.

Share:
12,146
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I've noticed a peculiar behavior in how python handles module names.

    If I write:

    import a.b
    import a
    

    and then attempt to reference something in module a.b, it works without a problem.

    However, if I attempt something only slightly different:

    import a.b
    import c as a
    

    and then attempt to reference something in module a.b, I get an error, saying:

    AttributeError: 'module' object has no attribute 'b'

    I understand that the obvious solution is simply to not have two different modules I refer to by the same name. However, I'm still curious what caused this change in behaviour. Why does one work and not the other?

  • Admin
    Admin over 11 years
    This makes a lot of since. I've been using java recently, so I considered "a" and "a.b" to be separate from each other. It's didn't occur to me that modules were being stored as objects and that I was overwriting them. Thank you.