[Python-Dev] Relative Package Imports

Tim Peters tim_one@email.msn.com
Sat, 18 Sep 1999 19:44:49 -0400


[Guido]
> ...
> In the Java world, the right solution exist: a better top-level naming
> scheme.  I forget what the exact rules are, but I seem to recall that
> Java has something of the same relative import rules af Python
> currently has: you can import a class from the same leaf package by
> its simple name, or you can import a class by its full name.

You can import only by the full name.  There are no shortcuts for anyone
ever in explicit Java imports.  The dodge is that to reference classes in
exactly the same package, you don't need an import statement at all (you
*can* have one, but then you need to use the fully qualified name).

The other twist is that all Java code is in *some* package, and code that
(wisely) doesn't want to live in the ill-defined unnamed package must
contain a package statement declaring which package it's a part of, like

package COM.dragonsys.justanexample;

The periods there actually have no semantic significance, and package
COM.dragonsys.notanexample has no more in common with the above than does
package ORG.python.guido.hitmeagain.  It's purely a conceptual thing that
justanexample and notanexample are *called* "subpackages" of package
COM.dragonsys in Java; although implementations are free (but not required)
to make up mappings between dotted package names and directory trees.

Anyway, the Java rules work fine wrt the issues that have been argued in
this thread.  Things that are worse than Python:

+ Magical implied import of same-package names is a PITA for readability and
maintenance.

+ Since subpackages are an illusion, and even packages aren't objects in
their own right, there's no possibility to create a shorthand local name for
the first M chunks of an N-chunk dotted access path (with M < N).  For
example, you may use java.awt.Font and java.awt.TextArea a lot.  You either
spell those out in full all the time, or do

import java.awt.Font;
import java.awt.TextArea;

and use just "Font" and "TextArea" later.  Making up a local name for just
the "java.awt" part isn't an option.  Which leads to gross overuse of the
following:

+ "import package.*" is Java's way of spelling "from package import *", and
because of the preceding is the only way to get convenient local names for
classes imported from other packages (note that can you can never import a
package/module in Java; you can only import a type name).  So most Java code
will do the above as

import java.awt.*;

and end up importing a gazillion names.  This sucks for the same reasons
"import *" sucks in Python, although Java catches the name conflicts at
compile time.

Things that are better than Python:

+ Name conflicts are caught at compile time.

+ At least in theory, the names of packages aren't constrained by platform
file name limitations or directory quirks.

+ Relatedly, explicitly naming the package a compilation unit belongs can be
a Good Thing.

+ They have *an* effective scheme for preventing package-name collisions.

> ...
> Note that I still resist the urge to start renaming all the existing
> standard modules -- too much breakage.  This will happen in 2.0.

At home, I dropped an empty __init__.py into the std Lib directory, so that
I can do e.g.

from Lib.random import randrange

in my own packages with their own random modules.  Works fine.  For 1.6 you
should pick some explicit way to *allow* explicit import of at least the std
library modules.  I suggest taking the name "Lib" <wink>.  Java is very cute
with its java.util.etc stuff, but longwindedness is not a virtue here --
"util" would have worked just as well and been just as clear.  Nobody should
write a package with a generic short name like "util" (or "Lib") anyway, so
rather than waste this pleasant little corner of the namespace the language
may as well reserve it for its own use.

heck-it-already-stole-"and"-and-"or"<wink>-ly y'rs  - tim