Created by: gwideman, Mar 14, 2011 12:31 am
Revised by: gwideman, Aug 28, 2014 2:43 pm (25 revisions)


Introduction

This page collects my notes on Python's import and from ... import ... statements. These notes are needed because of the various behaviors of the import statements, and difficulty finding documentation which is complete and clear.
The import statements have to work in conjunction with these other Python features which I have made notes upon elsewhere:
  • sys.path and what it typically includes
  • Package structure

Overview

The basic purpose of the import statement is to:
  • Identify one of the following items
    • An ordinary module
    • A package
    • A module within a package
    • An attribute of a module or package
  • Bind information about this external item to a variable local to the current module.
    • Code in the current module will then use this local-module variable to interact with the external item
Example:
import pickle
Using sys.path, this statement
  • finds the file pickle.py, and also
  • creates a variable pickle which can then be used like this:
myunpickler = pickle.load(... etc)

Two forms of import statement

Two distinct statements are involved in performing a variety of related functions. These are:
  • import x -- x may be a module or package
  • from a import b -- a may be a module or package; b can be a contained module or object (class, function etc)
These two forms, (along with optional addition of an as clause) allows the programmer to choose a suitable tradeoff between using lengthy dotted variable names versus shorter names that have more chance of name collisions.
Following sections will enumerate many examples to show the variations possible.
These examples have been tested in Python 3.1.

Example import statements

Basic syntaxes:
  • import pkgormod
  • import pkgormod, pkgormod, pkgormod
  • import pkgormod as newname
  • import pkgormod as newname, pkgormod as newname
pkgormod is an identifier which specifies a module or package. It may be a single name, or a string of names delimited by dots. These represent a path similar to a file path. Python appends this path to each of the directories in sys.path in turn until it finds the package or module specified.
Abbreviations: m: module, p: package, atr: some attribute, x: variable
Statement in caller
Finds and loads*
Creates attrib in caller
Usage in caller
Other reqmt
Note
import ma
ma.py
ma
x = ma.atra





x = ma.atra.atrb

Showing access to attribute of object atra, itself an attribute of ma.
import ma, mb, mc
ma.py, mb.py, mc.py
ma, mb, mc
x = ma.atra


import ma as za
ma.py
za
x = za.atra

Choosing a different name for the created variable
import pa
pa/__init__.py
pa
x = pa.atra

atra is attrib of package, i.e., of __init__.py



x = pa.mb.atrc
pa's __init__.py imports mb.
Caller can access mb, including mb.atrc as shown here.



x = pa.atrmc.atrd
pa's __init__.py imports mc as atrmc.
Caller can access mc via the atrmc attribute of __init__.py. Here atrd is an attribute in mc.
import pa.mb
pa/__init__.py and pa/mb.py
pa
x = pa.mb.atrc

NO reqmt for pa's __init__.py to have an import statement for mb.
This form imports pa into caller, then imports mb into pa. I.e., this statement in caller actually imports a module to package pa.
import pa.mb as zb
pa/__init__.py and pa/mb.py
zb
x = zb.atrc

Form seems similar to the form import pa.mb, but in this case it does not create a variable that provides access to pa per se.
___________________


_____________


Example from ... import ... statements

Basic syntaxes:
  • from pkgormod import modorobj
  • from pkgormod import modorobj as newname
  • from pkgormod import modorobj as newname, modorobj as newname

Statement in caller
Finds and loads [1]
Creates attrib in caller
Usage in caller
Other reqmt [2]
Note
Import from module





from ma import atrb
ma.py
atrb
x = atrb

Allows caller to use much shorter name for access to the attribute, but at risk of name collision.
from ma import atrb as zc
ma.py
zc
x = zc

Ditto but with new name
from ma import *
ma.py
Attribs matching all public attribs in ma
x = atrd
No __all__ in ma.
atrd corresponds to ma attribute atrd


Attribs matching ma's __all__ list

If ma has __all__ list

Import from package





from pa import mb
pa/__init__.py and pa/mb.py
mb
x = mb.atrb

In caller, usages of module mb require shorter name (no package part), but risk collisions
from pa import mb as zb
pa/__init__.py and pa/mb.py
zb
x = zb.atrb

Ditto but with new name
from pa import atrc
pa/__init__.py
atrc
x = atrc

Importing an object (in this case a variable) from pa's __init__.py into caller
[See notes below on import reference or copy semantics for objects]
from pa import atrc as zc
pa/__init__.py
zc
x = zc

Ditto, but with new name.
from pa import *
pa/__init__.py
Attribs matching all public attribs in pa
x = atrd,
x = mb.atrc
No __all__ in pa.
pa/__init__.py explicitly imports mb
atrd corresponds to pa/__init__.py attribute atrd.
Attributes imported from pa can include modules that pa/__init__.py explicitly imports (here mb).


Attribs matching pa's __all__ list

If pa has __all__ list
...again possibly including modules that pa explicitly imports and includes in its __all__ list
from pa.mb import atrc
pa/__init__.py and pa/mb.py
atrc
x = atrc

Import an attrib from a module.
from pa.mb import *
pa/__init__.py and pa/mb.py
Attribs matching all public attribs in mb
x = atrd
No __all__ in mb.
atrd corresponds to mb attribute atrd


Attribs matching mb's __all__ list
x = atrd
If mb has __all__ list







Relative import paths
(Can also use "as" clause, not shown here.)




If caller is a module within a package (or __init__.py), caller can use relative import path (starts with dot signifying same dir as caller's file).
from . import mb
same dir, mb.py
mb
x = mb.atrb


from .mb import atrc
same dir, mb.py
atrc
x = atrc


from .mb import *
same dir, mb.py
Attribs matching mb's
x = atrd

Same logic as from mb import *
from .. import mc
dir above, mc.py
mc
x = mc.atrf


from .pb import md
subdir pb, md.py
md
x = md.atrh


from .pb.md import atrg
subdir pb, md.py
atrg
x = atrg








from . import *
---
---
---
---
"Import all modules from this directory"
NOT ALLOWED but doesn't seem to throw error, just does nothing. Prohibited in PEP 328 -- Imports: Multi-Line and Absolute/Relative
___________________


_______


Note:
[1] Wherever xxx.py is shown, alternatively Python could load xxx.pyc or various other xxx.somethings corresponding to the xxx module.
[2] See also notes on package structure [xxx need link]

More on import's arguments

This section discusses some potential misconceptions regarding the arguments to the import and from...import statements:
import pkgormod
from pkgormod import modorobj
... also...
import pkgormod as newname
from pkgormod import modorobj as newname
  • pkgormodcan be
    • a single identifier
    • a string of identifiers separated by dot
    • For from ... importonly, pkgormod can have one or more leading dots signifying a relative directory path.
      • The dots mean the same thing as they do in a Windows or unix file path.
      • Lack of dots means an absolute path, to be combined with sys.path items.
  • modorobj
    • Must be a single name
  • newname
    • Must be an identifier
  • Not shown above: forms of import and from...import that list multiple imports in a single statement

Possible misconceptions

Can pkgormod refer to an an object?

Because the pkgormod component may consist of a string of identifiers separated by dots, and because the from...import statement can select objects within a module, it is easy to imagine that the dotted path might also be able to select objects.
So, for example, might this be possible:
from pkga.modb.objc import attrd
...where attrd is an attribute of object objc, itself an attribute of modb?
Answer: I am pretty sure this is never allowed.

Can modorobj contain a dotted path?

Answer: Judging by the grammar spec, modorobj can only be a single identifier. So where from...import refers to an object, that object must be a top-level attribute of a module (or package).

Can the pkgormod argument be a variable?

Example:
mypath = 'os.path'
import mypath
Answer: No. I tested this and found no combination that avoided a syntax error.

Semantics of imported attributes

When a from ... import ... is used to import specific attributes from a module or package, corresponding variables are created in the calling module. The semantics of these variables evidently follow the same semantics as for the arguments to functions in Python. These are:
  • For a variable holding an immutable value (simple types, immutable sequence?), the variable created is a copy of the value in the imported module.
  • For a variable holding a reference to a mutable object, the variable created is a reference to the same object.
Consequently, if the calling module assigns to the import-created variable, in the immutable case that value will only be seen by the calling module's copy of the variable. In the case of a reference to a mutable object, a change to that object by the calling module will be seen by the importee module.
[Partially verified by experimentation, and seems reasonable.]

Nagging Questions

  • When does relative import without a dot work? Only from __main__, or at other times?
    • It doesn't ever work. Import from same dir works for the main module because Python adds the main module's home dir to sys.path. (Adds it to beginning of the list, so it takes precedence over all other dirs in the path). At least, this is in Python 3.x. It's possible it used to work pre PEP 328 which mandates at least one dot for relative import.?
  • Does the __all__ variable work only in conjunction with the from x import *statement, or does it operate generally to limit visibility of attributes for all kinds of import statements?
    • The __all__ variable is solely for use with the from x import * statement. It does not limit visibility of attributes in any other way, so far as I can tell.
  • Is there a way for a package's __init__.py file to specify "import all modules in this package" without importing each of them explicitly?
    • Not that I know of. (There's probably some fancy reflection way to do it, I don't think there's a direct way to do it, since from...import * is prohibited.

Import statement grammar

Here is the grammar for the import statement as presented in The Python Language Reference. This is useful to gain confidence that virtually all variations have been covered above.
import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*
              | "from" relative_module "import" identifier ["as" name]
                ( "," identifier ["as" name] )*
              | "from" relative_module "import" "(" identifier ["as" name]
                ( "," identifier ["as" name] )* [","] ")"
              | "from" module "import" "*"
module          ::= (identifier ".")* identifier
relative_module ::= "."* module | "."+
name            ::= identifier
I note that the grammar show relative_module as prefixed by possibly zero dots. This would appear to be counter to PEP 328, which mandates at least one dot for relative import.