简体   繁体   中英

How does import works in python?

using matplotlib.pyplot doesn't work unlike the flask.app despite the similarity in the arrangement of pyplot.py and app.py in their packages. Here is the explanation.

The flask package contains the following modules.

__init__.py
app.py

Note. These are not the only modules that flask contains.

Whenever I want to use the app.py module i can do it in two ways. Here they are below.

>>> import flask
>>> flask.app
<module 'flask.app' from 'C:\\Python34\\lib\\site-packages\\flask\\app.py'>
>>> from flask import app
>>> app
<module 'flask.app' from 'C:\\Python34\\lib\\site-packages\\flask\\app.py'>
>>> 

Now let's take a look at the matplotlib package.

The matplotlib package contains the following modules.

__init__.py
pyplot.py

Note. These are not the only modules that matplotlib contains.

Now I will use the same approach as I did for flask to use the pyplot.py module but this time the first approach doesn't work and I do not understand why. Here it is.

>>> import matplotlib
>>> matplotlib.pyplot
Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    matplotlib.pyplot
AttributeError: 'module' object has no attribute 'pyplot'
>>> from matplotlib import pyplot
>>> pyplot
<module 'matplotlib.pyplot' from 'C:\\Python34\\lib\\site-packages\\matplotlib\\pyplot.py'>
>>> 

Being self learner can't help you with problem like this. Any idea is appreciated.

It is up to the author of the package to pick what gets automatically imported with the main package name or not.

Of course, these are complex examples, and it will be hard to find it in these projects source code, but it boils down to whether the code triggered by one package's root __init__.py file import the sub-packages explicitly or not.

So, it is as if Flask's __init__.py would contain a line like

from flask.app import app

(Although app could be a simple object instantiated directly in the __init__ file, not necessarily something in another sub-package)

In other words: Python does not perform auto-discovery and much less an "auto-import" of code in the sub-packages. For your own code, it may be nice to expose all sub-packages and public available classes, by explicitly importing then in the root __init__ file, for example, the __init__.py on my small "extradict" project is like this:

# coding:utf-8
from .version_dict import VersionDict
from .version_dict import OrderedVersionDict
from .normalized_dict import FallbackNormalizedDict
from .normalized_dict import NormalizedDict
from .map_getter import MapGetter
from .reciprocal_dict import BijectiveDict
from .extratuple import namedtuple
from .extratuple import defaultnamedtuple
from .extratuple import fastnamedtuple


__author__ = "João S. O. Bueno"
__version__ = "0.3.1"

And that make all those classes and factories directly available for anyone that imports "extradict".

If a particular sub-package is expensive in terms of initialization or used memory, it is better to not explicitly import it, and just let the users do that explicitly. For example, "pygame", a widely used project that provides easy multimedia access for 2D graphics and real-time keyboard and mouse-event handling, among other things, pre-imports the majority of its submodules automatically, but not the module dealing with computer cameras - so one has to do:

import pygame
import pygame.camera 

to make use of the webcam in the project. (Or from pygame import camera - it works the same).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM