views:

228

answers:

2

I have two related Python 'import' questions. They are easily testable, but I want answers that are language-defined and not implementation-specific, and I'm also interested in style/convention, so I'm asking here instead.

1)

If module A imports module B, and module B imports module C, can code in module A reference module C without an explicit import? If so, am I correct in assuming this is bad practice?

2)

If I import module A.B.C, does that import modules A and A.B as well? If so, is it by convention better to explicitly import A; import A.B; import A.B.C?

+6  A: 

The first thing you should know is that the Python language is NOT an ISO standard. This is rather different from C/C++, and it means that there's no "proper" way to define a language behaviour - CPython might do something just because it was coded that way, and Jython might do the other way round.

about your questions, remember that "importing" a module is a two-part operation: first the module is loaded - if it had never been, e.g. if it wasn't available in sys.modules, then a name is bound to that module in the local namespace.

hence:

1) Yes, you can reference whatever you want from module a by providing the proper namespace, e.g. you'll have to do something like

B.C.name = "something"

And I think this is very rarely done in Python programs and could be considered bad practice since it forces a "transitive dep" - if some module B implementation is refactored and doesn't depend on C anymore, it should continue offering the C module just for satisfying A deps.

Of course setting __ all __ can prevent this, and a good practice may be to put __ all __ in all your modules, and export just the symbols you want to be really public.

2) Yes and no. Doing

import a.b.c.d

performs the first import phase (loading) on all modules, but the second just on a (and, recursively, in b with respect to c, etc) but all the modules in the chain must be referenced by full namespace; after such an import, you can do

a.something
a.b.something
a.b.c.something

but you can't do

c.something
b.something

I must admit that kind of usage is pretty rare as well; I generally prefer the "from module import something" way-to-import, and generally you just ask for what you need - such nesting is neither common in libraries, nor its usage is that common.

Many times there're "outer packages", just used for organization, which hold modules with classes. It's very likely that a, b, c above are just packages, and d is a module which truly holds classes, functions and other objects. So the proper usage would be:

from a.b.c.d import name1, name2, name3

I hope this satifies your curiosity.

Alan Franzoni
Thanks for the detailed answer!
Cory Petosky
While not ISO, there is a Python language reference which defines the "proper" behavior, including imports: http://docs.python.org/reference/simple_stmts.html#the-import-statementThe language reference points out CPython implementation details, but aims to be a generic specification of the language, so that it is not all implementation-dependent.
Matt Good
+4  A: 

Alan's given a great answer, but I wanted to add that for your question 1 it depends on what you mean by 'imports'.

If you use the from C import x syntax, then x becomes available in the namespace of B. If in A you then do import B, you will have access to x from A as B.x.

It's not so much bad practice as potentially confusing, and will make debugging etc harder as you won't necessarily know where the objects have come from.

Daniel Roseman
That's a useful clarification, thanks. I'd been thinking of `import` as similar to Java-style package imports, but clearly that similarity is merely superficial.
Cory Petosky