[Tutor] importing modules [from [module] import * is evil]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Wed Jul 23 05:13:01 2003


On Mon, 21 Jul 2003, Luiz Siqueira Neto wrote:

> How can I import modules inside of a directory in a root of my project?
>
> in java I use import dir.package.*


Hi Luiz,

Let's clarify one point: your question is actually two separate questions.
*grin*

> How can I import modules inside of a directory in a root of my project?

Python searches for modules that it can find within the 'sys.path'
variable, so you can alter sys.path to include the root of your project
directory.

In Java, we deal with an environmental variable called the "CLASSPATH".
In Python, the analogous variable is "PYTHONPATH", but by default, it
includes the current directory already.  If you need to add a hardcoded
path, you can modify sys.path as Michael recommends.



> in java I use import dir.package.*

This second question is different because it asks: "How do I pull the
contents of a package into my namespace?"  For that, see:

http://www.python.org/doc/current/tut/node8.html#SECTION008410000000000000000

Warning: using 'from [module] import *' is often not a good idea --- it
works best only if a module is specifically designed to support it.  It
can be potentially problematic because it pulls everything from the module
into our namespace, including names that can conflict with builtins.


Java programmers will run into this problem too, but it's slightly less of
an issue because the problem pops up at compile time rather than runtime.
Since you have experience in Java, let's talk Java.  *grin*

Let's say we're dealing with two classes in separate packages:  'A/Foo'
and 'B/Foo':

/***
  * A/Foo.java
  **/
package A;
public class Foo {
    public void sayHello() {
        System.out.println("foo!");
    }
}
/***/



/***
  * B/Foo.java
  **/
package B;
public class Foo {
    public void sayHello() {
        System.out.println("foo?");
    }
}
/***/


Ok, the stage is set.  What happens if we do something like this?

/***
 * Test.java
 */
import A.*;
import B.*;
public class Test {
    public static void main(String[] args) {
        Foo f = new Foo();
        f.sayHello();
    }
}
/***/

Java will (or had better!) detect this as a compile-time error.  Here's
what it looks like on my end:

######
bash-2.05a$ javac Test.java
Test.java:5: reference to Foo is ambiguous, both class B.Foo in B and
class A.Foo in A match
        Foo f = new Foo();
        ^
Test.java:5: reference to Foo is ambiguous, both class B.Foo in B and
class A.Foo in A match
        Foo f = new Foo();
                    ^
2 errors
######

That's the important thing to realise: doing a "glob" of our modules can
result in collisions.  But Java opts to trigger a compile time error to
force the programmer to deal with this.  Not a good thing if you're the
author of B, but not the original designer of the A package, but it's
still should be managable in Java.


Ok, let's put on our Python hat now.  We need to get an analogous
situation going.

###
bash-2.05a$ cat A.py
def sayHello():
    print "Hello, this is A!"

bash-2.05a$ cat B.py
def sayHello():
    print "Hello, this is B"


bash-2.05a$ python
Python 2.2 (#1, 11/12/02, 23:31:59)
[GCC Apple cpp-precomp 6.14] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from A import *
>>> from B import *
>>> sayHello()
Hello, this is B
###

Rather than conflict with an error, Python will allow one 'import *' to
override the other.  This might be what the programmer expects... but then
again, maybe not.  So it's not a SyntaxError --- it's a bit more insidious
in Python, so not such a nice thing to deal with.

Consequently, most Python programmers will recommend the avoidance of
'import *' unless the package has been really designed with these issues
in mind.  ('Tkinter' and 'pygame', for example.)  Otherwise, it's better
to either fully qualify module imports, or to be be more specific:

###
import A
from B import sayHello
A.sayHello()
sayHello()
###

That way, we can avoid the variable name collision altogether.



Anyway, hope this helps!