views:

133

answers:

4

main.py:

import subone
import subtwo

subone.py:

a = 'abc'

subtwo.py:

print subone.a

Running python main.py throws a NameError: name 'subone' is not defined. I expected it to print 'abc'.

Refactoring it to use from import and classes doesn't help:

main.py:

from subone import *   # Only using from X import * for example purposes.
from subtwo import *

print 'from main.py:', a.out

subone.py:

class A:
    out = 'def'

a = A()

subtwo.py:

# This throws NameError: name 'a' is not defined
print a.out

# This throws NameError: name 'A' is not defined
b = A()
print b.out

BUT it will print 'from main.py: def'. (It works when using import too.)

Why does it work this way? It seems like once subone is imported, it should be available to subtwo.

Is it because it's bad programming to have imported modules depend on each other without going through their 'parent' module? Is there another, standard way to do this?

Update:

I now understand that the first example will not work because the line print subone.a doesn't recognize the name subone, it not being in subtwo's namespace (even though it's in main.py's), and it is being called from within the module subtwo. This can be fixed by using import subone at the top of subtwo.py -- it will not re-load the module but will add it to subtwo's namespace so subtwo can use it.

But what about this:

main.py:

from subone import Nugget
from subtwo import Wrap

wrap = Wrap()
print wrap.nugget.gold

subone.py:

class Nugget:
    gold = 'def'

subtwo.py:

class Wrap:
    nugget = Nugget()

I would think that since Wrap and Nugget are both loaded directly into main's namespace, that they would use main's namespace and be able to reference each other, but it throws a NameError: name 'Nugget' is not defined. IS IT because Wrap is evaluated/checked from within subtwo's namespace BEFORE being loaded into main's namespace?

+2  A: 

The subtwo namespace will be totally empty unless you import subone into it.

As far as programming practices, subone and subtwo can depend on each other if so desired, you just need to explicitly link them (with an import)

Nick T
Okay, but why doesn't it work even when using from - import, which loads everything into main's namespace?
willell
It doesn't matter, when `subtwo` runs (when main `import`'s it), nothing is in *its* namespace.
Nick T
It might help to remember that `import` in Python is not like `include` in other languages.
Paul D. Waite
You're right, I learned PHP first.
willell
+3  A: 

Can you explain why you feel like subone should be available to subtwo, when subone has been imported by main? As it is, subtwo.py can be compiled without knowing what main.py has imported.

Also, if a second program imports subtwo.py, should subtwo's knowledge of subone depend on which of two main programs is importing subtwo? This would reduce reusability of subtwo.

It seems like you're thinking of the compilation as a process with a defined order, accumulating state information: compile main.py, during which we compile/import subone.py, accumulating information from it, and then we compile/import subtwo.py, using the information we've already accumulated.

Instead, the compilation of each module is independent of others, unless dependencies are declared. This makes it much easier to reuse and maintain code: there are fewer hidden dependencies.

Is it because it's bad programming to have imported modules depend on each other without going through their 'parent' module?

Not as such... It's just bad programming to have module 2 depend on module 1 without saying so, i.e. without module 2 declaring "I depend on module 1".

LarsH
Ah, I see. The way you describe it helps. I think I've been used to PHP's `include` and `require` statements, which directly embed code. Instead, modules are objects which need to be called.
willell
@willell: I've never used PHP, but C is similar with the preprocessor `#include` just pasting the entire file there. Regardless, some sort of implicit dependency like that just doesn't seem smart regardless of language.
Nick T
@willell, that makes sense... the way you're thinking of it indeed matches how PHP and C include mechanisms work. However you can see how that leads to dependencies that are difficult to trace... in order to find out what file B depends on, you have to look at all the places where file B is included. So there's a fundamental difference between "including a file" and "importing a module". The former is more of a simple, literal insertion of a text string, unconscious of the semantic consequences. The latter is more of a conceptual linking of one program component to another.
LarsH
@LarsH - Yeah, I gotcha. What you call conceptual linking is a big part of the reason I'm using Python anyway. The only thing I'm still confused about: If `from import` loads all module-level objects into the current namespace, then why can't those objects reference each other? Is it because those objects are evaluated within their respective modules BEFORE they're loaded into the current module?
willell
+5  A: 

If you modified your subtwo.py this way then it will work

import subone
print subone.a

When you do subone.a in subtwo.py, you are trying to access the namespace subone in subtwo.py and in the namespace "subone", there should be a attribute "a".

When you do - import subone in subtwo.py, then subone is added to the namespace and subone namespace has attribute a. so subone.a will work.

I would also suggest that you play with dir() to see how namespaces are being added.

In subtwo.py, you can do the following:

print dir()
import subone
print dir()
print subone.a

Similarly, try adding "print dir()" before and after your import statements and the idea should become clear to you.

"import x" adds 'x' to the current modules namespace while "from x import * " will add all the module level attributes directly into current module namespace

So in your above first example of main.py, subone.py and subtwo.py, the namespace in main.py will contain 'subone' and 'subtwo' while subtwo.py will have an empty namespace and can not access subone.a.

[Edit: Some more explanations] Consider following files: main.py

print "Before importing subone : ", dir()
import subone
print "After importing subone and before importing subtwo: ",  dir()
import subtwo
print "After importing subone and subtwo: ", dir()

subone.py

a = 'abc'

subtwo.py

print dir()
import subone
print "module level print: ", subone.a
print dir()
def printX():
    print subone.a

And the output of running main.py:

Before importing subone :  ['__builtins__', '__doc__', '__file__', '__name__', '__package__']
After importing subone and before importing subtwo:  ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'subone']
['__builtins__', '__doc__', '__file__', '__name__', '__package__']
module level print:  abc
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'subone']
After importing subone and subtwo:  ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'subone', 'subtwo']

Some Observations

  1. You will notice that importing a module subtwo.py, the print statement is executed immediately.
  2. So when subone and subtwo are imported in main.py, the namespace of main.py is augmented.
  3. That does not mean that namespace of subtwo will be augmented. so "a" is available only in main.py via subone.a
  4. When we do import subone in subtwo.py then the namespace of subtwo is augmented with subone and attribute a of module subone is available in subtow.py via subone.a
pyfunc
This is very helpful. dir() really makes things clear for me. My only question (as I commented below) is that if "from x import *" adds all the module level attributes directly into the current namespace, then why can't those attributes access each other?
willell
That import doesn't actually change the scope of the attributes, it merely copies their definition to the local scope.
Ignacio Vazquez-Abrams
@willell: Ignacio Vazquez-Abrams is correct. I should have been more clear. This is not the same as copying the code as it happens in case of #include in "C". The imported modules are loaded and evaluated already. if you had a print statement in an imported module, it would already have been evaluated.
pyfunc
@Ignacio: You're saying each attribute has its own namespace, inherited from the module it came from?
willell
@pyfunc: Gotcha. So in my third example in my updated question, `Wrap` and `Nugget` are evaluated (and therefore raise the NameError) before their definitions are loaded into `main`'s namespace?
willell
@willell: Right, I edited my answer to explain that. :)
pyfunc
Each attribute has its own scope, which the reference carries around with it.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams: @willell: +1 That explains it all.
pyfunc
A: 

Regarding your second example, "main.py" knows about Nugget but "subtwo.py" doesn't.

I think it would help to think of it this way. Every module (file) has to work as if the only other modules that exist are the ones that it imports. In this case "subtwo.py" would not be able to run by itself because it hasn't imported Nugget. Essentially "subtwo.py" doesn't know what "main.py" knows. It shouldn't, because it could be called from anywhere by anyone, and it can't rely on anyone else importing the stuff that it needs.

Davy8