"Import as" isn't recognized, normal import is
Asked Answered
K

3

5

I'm playing around with matplotlib to understand its structure better and I'm confused by the following piece of code:

import matplotlib as mpl
from mpl import pyplot as plt # ModuleNotFoundError : No module named 'mpl'
mpl.pyplot # AttributeError: module 'matplotlib' has no attribute 'pyplot'

If on the other hand I abstain from importing matplotlib as a different name and execute instead

import matplotlib
from matplotlib import pyplot as plt #works!

the things work.

Even more crazy, if I "combine" these two import matplotlib as mpl from matplotlib import pyplot as plt #works! mpl.pyplot.get_backend() # works

I can curiously access attributes from pyplot even if I reference it as mpl.pyplot.

What is going on here, why does

  • from mpl import pyplot as plt throws a ModuleNotFoundError?

  • import mpl.pyplot not work? Since the error message indcates that mpl was correctly resolved to matplotlib, yet still pyplot couldn't be found...

  • referencing pyplot as mpl.pyplot not cause an error in my last example?

(Note that I do know of course that the preferred way is to import pyplot as import matplotlib.pyplot as plt but the point of my investigation is precisely to understand what fails and why when I ventured outside the welltrodden streets of code.)

Kenway answered 20/3, 2022 at 19:5 Comment(6)
When you take a look at the importlib documentation you can see that with your first example it's searching for a mpl package which doesn't existWiese
@Wiese I read through docs.python.org/3/library/… but I don't understand how that abstract definition relates to my examples, since no mentioning is made how the search for modules is actually conducted ...Kenway
Sorry for the late reply. The import mechanism calls the Finders find_spec method with the package name (in your case mpl ) util a spec for the module is returned or all finders on sys.meta_path have been tried (fullname as string, later normally the same as __name__ ). With this the finder (normally) just searches the sys.path for python classes / modules named that way. Once a finder has found and returned the spec the Loader will be called to create / execute the imported module itself.Wiese
Thanks for the info, I was able to read from here (docs.python.org/3/reference/import.html#importsystem) a bit about how Finders and Loaders work and from here (docs.python.org/3/reference/…) the abstract syntax of the import module. I'm quoting from the latter: 1) "If the module name is followed by as, then the name following as is bound directly to the imported module" and 2) "The from form uses a slightly more complex process: find the module specified in the from clause, loading and initializing it if necessary".Kenway
Wouldn't 1) and 2) thus mean that in my code above that mpl is already "associated" to the matplotlib module and therefore using from mpl [...], that mpl should be resolved to the matplotlib module?Kenway
(I have edited the question to emphasize this weird behavior of import.)Kenway
F
9

The as part in an import statement is just syntactic sugar for assigning the imported module to a variable with the given name. The import documentation describes it as such:

If the module name is followed by as, then the name following as is bound directly to the imported module.

"Bound" in this context means doing an assignment to the given name. The following statement

import someModule as someName

Is equivalent to this code:

import someModule
someName = someModule

So, when you do import matplotlib as mpl, all you do is create a variable called mpl. This has no effect on any further import statements, as import statements do not care about your local variables, but search for python packages and modules - and an import as statement cannot change the package or module name of the imported element. Which is a good thing, as you do not want your import statements to fail just because another import 5 lines earlier used a conflicting name in an as clause.

Now, why you're getting weird results with the import mpl.pyplot statement - no idea, it shouldn't work. You can see the expected behaviour if you try the following:

import os as asdf
import asdf.path    #ModuleNotFoundError: no module named 'asdf'

Tested with python 3.10.2 on Archlinux. If your example is reproducible, then you might have found a weird bug or undefined behaviour in your specific python version, or have some other issue (e.g. a mpl module in your path... although that on its own wouldn't explain why you get an error message about matplotlib instead of mpl).

In conclusion, all as does is assigning a name to the imported object, so a name assigned with as cannot be used as a source in another import statement.


On package imports and why matplotlib.pyplot gives an error:

Importing a package only imports the package itself, not any of its subpackages or modules. A package can explicitly import submodules in its __init__.py, so if the matplotlib init file would contain a statement like from . import pyplot line then accessing matplotlib.pyplot would work. There are however many reasons why a package might choose not to import any submodules, such as time and resources required to import and initialize them.

Fannie answered 23/3, 2022 at 16:13 Comment(3)
+1 "Bound" in this context means doing an assignment to the given name." & " import statements do not care about your local variables" this was spot on and finally clarified it for me, thanks!Kenway
Ah,I realized that my code had a small error, the command that lead to AttributeError was not import mpl.pyplot but rather just mpl.pyplot (the text must have gotten scrambled as I was copying, deleting & copying again code from my source file), so I needlessly confused myself even more. The behavior that actually was confusing was: Why is mpl.pyplot giving this error? (matplotlib.pyplot BTW gives the same error, so there's no bug here :) When I execute from matplotlib import pyplot as plt it works, yet I can't directly execute matplotlib.pyplot, which confuses me.Kenway
@Kenway Ok, that explains it. Matplotlib is a package, and subpackages or modules of a package are not usually imported when you import the package itself, unless the __init__.py of the package explicitly triggers the import.Fannie
P
3

Everything in python is a object, but when you import matplotlib you are importing all library but you cannot change your functions names, the library will looking for plt from matplotlib import pyplot as plt in this case. You can use plt directly but you cannot use mpl.plt.

When you tried it :

import matplotlib as mpl
from mpl import pyplot as plt # ModuleNotFoundError : No module named 'mpl'
mpl.pyplot 

You should import correctly:

   import matplotlib as mpl
   from mpl import pyplot 
   mpl.pyplot 

'As' change the module name what you going to use in your project, but not from another import. But if you use plt directly it is going works. Try this code to understand :

import matplotlib as mpl
import matplotlib
print(type(matplotlib))
print(type(mpl))
from matplotlib import pyplot as plt# ModuleNotFoundError : No module named 'mpl'
from matplotlib import pyplot

print(type(plt))
print(type(mpl.pyplot))
plt
mpl.pyplot
Preceptive answered 29/3, 2022 at 21:35 Comment(0)
M
2

When you do import module as mdl, it doesn't change the module name. It only affects other statements when you actually use it. But the name doesn't change in the actual python lib or the external library. So what you can do is this:

import matplotlib
from matplotlib import pyplot as plt

or just from matplotlib import pyplot as plt

This is my answer...

Manufacturer answered 26/3, 2022 at 19:20 Comment(3)
What are you using matplotlib for?Manufacturer
It would be more specific if you told us what your using it for.Manufacturer
And we can help you moreManufacturer

© 2022 - 2024 — McMap. All rights reserved.