Learning Python - Mark Lutz [318]
In other words, “package relative imports” in 3.0 really just boil down to a removal of 2.6’s special search path behavior for packages, along with the addition of special from syntax to explicitly request relative behavior. If you wrote your package imports in the past to not depend on 2.6’s special implicit relative lookup (e.g., by always spelling out full paths from a package root), this change is largely a moot point. If you didn’t, you’ll need to update your package files to use the new from syntax for local package files.
Module Lookup Rules Summary
With packages and relative imports, the module search story in Python 3.0 in its entirety can be summarized as follows:
Simple module names (e.g., A) are looked up by searching each directory on the sys.path list, from left to right. This list is constructed from both system defaults and user-configurable settings.
Packages are simply directories of Python modules with a special __init__.py file, which enables A.B.C directory path syntax in imports. In an import of A.B.C, for example, the directory named A is located relative to the normal module import search of sys.path, B is another package subdirectory within A, and C is a module or other importable item within B.
Within a package’s files, normal import statements use the same sys.path search rule as imports elsewhere. Imports in packages using from statements and leading dots, however, are relative to the package; that is, only the package directory is checked, and the normal sys.path lookup is not used. In from . import A, for example, the module search is restricted to the directory containing the file in which this statement appears.
Relative Imports in Action
But enough theory: let’s run some quick tests to demonstrate the concepts behind relative imports.
Imports outside packages
First of all, as mentioned previously, this feature does not impact imports outside a package. Thus, the following finds the standard library string module as expected:
C:\test> c:\Python30\python
>>> import string
>>> string
But if we add a module of the same name in the directory we’re working in, it is selected instead, because the first entry on the module search path is the current working directory (CWD): # test\string.py print('string' * 8) C:\test> c:\Python30\python >>> import string stringstringstringstringstringstringstringstring >>> string In other words, normal imports are still relative to the “home” directory (the top-level script’s container, or the directory you’re working in). In fact, relative import syntax is not even allowed in code that is not in a file being used as part of a package: >>> from . import string Traceback (most recent call last): File " ValueError: Attempted relative import in non-package In this and all examples in this section, code entered at the interactive prompt behaves the same as it would if run in a top-level script, because the first entry on sys.path is either the interactive working directory or the directory containing the top-level file. The only difference is that the start of sys.path is an absolute directory, not an empty string: # test\main.py import string print(string) C:\test> C:\python30\python main.py # Same results in 2.6 stringstringstringstringstringstringstringstring Imports within packages Now, let’s get rid of the local string module we coded in the CWD and build a package directory there with two modules, including the required but empty test\pkg\__init__.py file (which I’ll omit here): C:\test> del string* C:\test> mkdir pkg # test\pkg\spam.py import eggs # <== Works in 2.6 but not 3.0! print(eggs.X) # test\pkg\eggs.py X = 99999 import string print(string) The first file in this package tries to import the second with a normal import statement. Because this