views:

61

answers:

4

Let's assume I have a main script, main.py, that imports another python file with import coolfunctions and another: import chores

Now, suppose coolfunctions also uses stuff from chores, hence I declare import chores inside coolfunctions.

Since both main.py, and coolfunctions import chores ~ is this redundant? Is there any other way of doing this? Am I doing it correctly?

I'm confused about how python projects should be structured in general. I have a "conf.py" file, that I import for a bunch of variables ~ is this a module or not? I load this conf file in multiple places as well.

+1  A: 

No, this isn't redundant - it's fine to import chores in both the main module and coolfunctions.

The exact import mechanics of Python are complex (for example, module imports are only done once, meaning in your case that the actual parsing and loading of the chores module will only happen once, which is a nice optimization) but in general you shouldn't worry about it because it just works.

Each Python file is a module, so your conf.py is also a module.

Eli Bendersky
A: 

It is always the best practice to import all necessary modules in the file that uses them. Take for example:

A.py contains: import coolfunctions

B.py contains: import A

Main.py contains: import B and uses functions that are defined in A.py (this is possible because by importing B, Main.py has imported everything that B imports)

If in the future, you change B.py to function without needing to import A.py and therefore remove the import A, then your Main.py will suffer the loss of not having imported A.

inspectorG4dget
I'm not sure that Main.py can make direct calls to functions in A, such as A.funkyfunctions() without importing A. Are you sure of this?
Deniz
No, it's most definitely **not** the case that "by importing B, Main.py has imported everything that B imports". By doing `import B`, `Main` has imported exactly one identifier: `B`. It can use `B.A` if and only if `B` defines (including `import`s) identifier `A`, and so on.
Alex Martelli
@Alex Martelli: I should have worded my response better, but I meant to say what you have said. Everything that B imports is now accessible to Main.py, because Main.py has imported B.
inspectorG4dget
+1  A: 

If two modules want to use chores, then each one must import chores (or some equivalent import). Each import creates a name binding only in the namespace of the module that does the import; that is, import's namespace effect is local to a module's namespace.

This is good, because by looking at a module's code you can (barring pathological cases) know where each name is bound to by the import statements that explicitly bind modules or module attributes to names. Imports made in other modules won't affect this module's namespace.

bignose
+1  A: 

Each module X should import all (and only) the modules Y, Z, T, ... whose functionality it requires, without any worry about what other modules Fee, Fie, Foo ... (if any) may have already done part or all of those imports, or may be going to do so in the future.

It would make a module extremely fragile (indeed, it would be the very opposite of modularity!) if each module had to worry about such subtle, "covert-channel" effects.

What other modules Y, Z, T, ..., each module X chooses to import (if any) is part of X's implementation details, and shouldn't concern anybody except the developers who are coding, testing, or maintaining X.

In order to ensure that this is the case, and that this clearly-best strategy of decoupling can and will fully be followed by sane code, Python "caches" modules as they get imported: a module is "loaded" only once per run of a program, the first time anybody imports it (or anything from inside it) -- all other imports use the same object obtained by that first loading, which Python keeps in a cache (which is specified as being the dict sys.modules, but you need to know that detail only for somewhat-advanced programming techniques... don't worry about it, 98.7% of the time -- just remember that "import is cheap"!-).

Sure, a conf.py that you use from several other modules via import conf is definitely a module (you may think you're loading it multiple times, but you aren't unless you're using pretty advanced and deliberate techniques indeed for the purpose) -- why shouldn't it be?

Alex Martelli
If the above answer seems a bit confusing, know that you can put a line like ``print 'loading mymodule'`` right into the top level of mymodule.py. You will see the print statement execute the first time it is imported, but not the second time it is imported.
Charles Merriam
`python -v yourmain.py` also helps;-).
Alex Martelli