The negatives you list for IM/FPIM can often be ameliorated by appropriate use of an as
clause. from some.package import mymodulewithalongname as mymod
can usefully shorten your code and enhance its readability, and if you rename mymodulewithalongname
to somethingcompletelydifferent
tomorrow, the as
clause can be used as a single statement to edit.
Consider your pro-FMIF point 3 (call it R for redirection) vs your pro-FPIM point 2 (call it F for flexibility): R amounts to facilitating the loss of integrity of module boundaries, while F strenghtens it. Multiple functions, classes and variables in a module are often intended to work together: they should not be independently switched to different meanings. For example, consider module random
and its functions seed
and uniform
: if you were to switch the import of just one of them to a different module, then you'd break the normal connection between calls to seed
and results of calls to uniform
. When a module is well designed, with cohesion and integrity, R's facilitation of breaking down the module's boundaries is actually a negative -- it makes it easier to do something you're better off not doing.
Vice versa, F is what enables coordinated switching of coupled functions, classes, and variables (so, generally, of entities that belong together, by modularity). For example, to make testing repeatable (FPIM pro-point 1), you mock both seed
and random
in the random
module, and if your code follows FPIM, you're all set, coordination guaranteed; but if you have code that has imported the functions directly, you have to hunt down each such module and repeat the mocking over and over and over again. Making tests perfectly repeatable typically also requires "coordinated mocking" of date and time functions -- if you use from datetime import datetime
in some modules, you need to find and mock them all (as well as all those doing from time import time
, and so forth) to ensure that all the times received when the various parts of the system ask "so what time is it now?" are perfectly consistent (if you use FPIM, you just mock the two relevant modules).
I like FPIM, because there's really not much added value by using a multiply qualified name rather than a singly qualified one (while the difference between barenames and qualified names is huge -- you get so much more control with a qualified name, be it singly or multiply, than you possibly ever can with a barename!).
Ah well, can't devote all of the working day to responding to each and every one of your points -- your question should probably be half a dozen questions;-). I hope this at least addresses "why is F better than R" and some of the mocking/testing issues -- it boils down to preserving and enhancing well-designed modularity (via F) rather than undermining it (via R).
__import__
is a low-level hook function that's used to import modules; it can be used to import a module dynamically by giving the module name to import as a variable, something the import
statement won't let you do.
importlib.import_module()
is a wrapper around that hook* to produce a nice API for the functionality; it is a very recent addition to Python 2, and has been more fleshed out in Python 3. Codebases that use __import__
generally do so because they want to remain compatible with older Python 2 releases, e.g. anything before Python 2.7.
One side-effect of using __import__
can be that it returns the imported module and doesn't add anything to the namespace; you can import with it without having then to delete the new name if you didn't want that new name; using import somename
will add somename
to your namespace, but __import__('somename')
instead returns the imported module, which you can then ignore. Werkzeug uses the hook for that reason in one location.
All other uses are to do with dynamic imports. Werkzeug supports Python 2.6 still so cannot use importlib
.
* importlib
is a Pure-Python implementation, and import_module()
will use that implementation, whist __import__
will use a C-optimised version. Both versions call back to importlib._bootstrap._find_and_load()
so the difference is mostly academic.
Best Answer
The difference between
import module
andfrom module import foo
is mainly subjective. Pick the one you like best and be consistent in your use of it. Here are some points to help you decide.import module
import
statements. Don't need to add any additional imports to start using another item from the modulemodule.foo
in your code can be tedious and redundant (tedium can be minimized by usingimport module as mo
then typingmo.foo
)from module import foo
foo
import
statementfoo
. For example, it's less clear whatceil()
does compared tomath.ceil()
Either method is acceptable, but don't use
from module import *
.For any reasonable large set of code, if you
import *
you will likely be cementing it into the module, unable to be removed. This is because it is difficult to determine what items used in the code are coming from 'module', making it easy to get to the point where you think you don't use theimport
any more but it's extremely difficult to be sure.