The coverage of package imports so far has focused mostly on importing package files from outside the package. Within the package itself, imports of same-package files can use the same full path syntax as imports from outside the package—and as we’ll see, sometimes should. However, package files can also make use of special intrapackage search rules to simplify import statements. That is, rather than listing package import paths, imports within the package can be relative to the package.
The way this works is version-dependent: Python 2.X implicitly searches package directories first on imports, while 3.X requires explicit relative import syntax in order to import from the package directory. This 3.X change can enhance code readability by making same-package imports more obvious, but it’s also incompatible with 2.X and may break some programs.
If you’re starting out in Python with version 3.X, your focus in this section will likely be on its new import syntax and model. If you’ve used other Python packages in the past, though, you’ll probably also be interested in how the 3.X model differs. Let’s begin our tour with the latter perspective on this topic.
As we’ll learn in this section, use of package relative imports can actually limit your files’ roles. In short, they can no longer be used as executable program files in both 2.X and 3.X. Because of this, normal package import paths may be a better option in many cases. Still, this feature has found its way into many a Python file, and merits a review by most Python programmers to better understand both its tradeoffs and motivation.
The way import operations in packages work has changed slightly in Python 3.X. This change applies only to imports within files when files are used as part of a package directory; imports in other usage modes work as before. For imports in packages, though, Python 3.X introduces two changes:
It modifies the module import search path semantics to skip the package’s own directory by default. Imports check only paths on the sys.path search path. These are known as absolute imports.
It extends the syntax of from statements to allow them to explicitly request that imports search the package’s directory only, with leading dots. This is known as relative import syntax.
These changes are fully present in Python 3.X. The new from statement relative syntax is also available in Python 2.X, but the default absolute search path change must be enabled as an option there. Enabling this can break 2.X programs, but is available for 3.X forward compatibility.
The impact of this change is that in 3.X (and optionally in 2.X), you must generally use special from dotted syntax to import modules located in the same package as the importer, unless your imports list a complete path relative to a package root on sys.path, or your imports are relative to the always-searched home directory of the program’s top-level file (which is usually the current working directory).
By default, though, your package directory is not automatically searched, and intrapackage imports made by files in a directory used as a package will fail without the special from syntax. As we’ll see, in 3.X this can affect the way you will structure imports or directories for modules meant for use in both top-level programs and importable packages. First, though, let’s take a more detailed look at how this all works.
In both Python 3.X and 2.X, from statements can now use leading dots (“.”) to specify that they require modules located within the same package (known as package relative imports), instead of modules located elsewhere on the module import search path (called absolute imports). That is:
Imports with dots: In both Python 3.X and 2.X, you can use leading dots in from statements’ module names to indicate that imports should be relative-only to the containing package—such imports will search for modules inside the package directory only and will not look for same-named modules located elsewhere on the import search path (sys.path). The net effect is that package modules override outside modules.
Imports without dots: In Python 2.X, normal imports in a package’s code without leading dots currently default to a relative-then-absolute search path order—that is, they search the package’s own directory first. However, in Python 3.X, normal imports within a package are absolute-only by default—in the absence of any special dot syntax, imports skip the containing package itself and look elsewhere on the sys.path search path.
For example, in both Python 3.X and 2.X a statement of the form:
from . import spam # Relative to this package
instructs Python to import a module named spam located in the same package directory as the file in which this statement appears. Similarly, this statement:
from .spam import name
means “from a module named spam located in the same package as the file that contains this statement, import the variable name.”
The behavior of a statement without the leading dot depends on which version of Python you use. In 2.X, such an import will still default to the original relative-then-absolute search path order (i.e., searching the package’s directory first), unless a statement of the following form is included at the top of the importing file (as its first executable statement):
from __future__ import absolute_import # Use 3.X relative import model in 2.X
If present, this statement enables the Python 3.X absolute-only search path change. In 3.X, and in 2.X when enabled, an import without a leading dot in the module name always causes Python to skip the relative components of the module import search path and look instead in the absolute directories that sys.path contains. For instance, in 3.X’s model, a statement of the following form will always find a string module somewhere on sys.path, instead of a module of the same name in the package:
import string # Skip this package's version
By contrast, without the from __future__ statement in 2.X, if there’s a local string module in the package, it will be imported instead. To get the same behavior in 3.X, and in 2.X when the absolute import change is enabled, run a statement of the following form to force a relative import:
from . import string # Searches this package only
This statement works in both Python 2.X and 3.X today. The only difference in the 3.X model is that it is required in order to load a module that is located in the same package directory as the file in which this appears, when the file is being used as part of a package (and unless full package paths are spelled out).
Notice that leading dots can be used to force relative imports only with the from statement, not with the import statement. In Python 3.X, the import modname statement is always absolute-only, skipping the containing package’s directory. In 2.X, this statement form still performs relative imports, searching the package’s directory first. from statements without leading dots behave the same as import statements—absolute-only in 3.X (skipping the package directory), and relative-then-absolute in 2.X (searching the package directory first).
Other dot-based relative reference patterns are possible, too. Within a module file located in a package directory named mypkg, the following alternative import forms work as described:
from .string import name1, name2 # Imports names from mypkg.string from . import string # Imports mypkg.string from .. import string # Imports string sibling of mypkg
To understand these latter forms better, and to justify all this added complexity, we need to take a short detour to explore the rationale behind this change.
Besides making intrapackage imports more explicit, this feature is designed in part to allow scripts to resolve ambiguities that can arise when a same-named file appears in multiple places on the module search path. Consider the following package directory:
mypkg\
__init__.py
main.py
string.py
This defines a package named mypkg containing modules named mypkg.main and mypkg.string. Now, suppose that the main module tries to import a module named string. In Python 2.X and earlier, Python will first look in the mypkg directory to perform a relative import. It will find and import the string.py file located there, assigning it to the name string in the mypkg.main module’s namespace.
It could be, though, that the intent of this import was to load the Python standard library’s string module instead. Unfortunately, in these versions of Python, there’s no straightforward way to ignore mypkg.string and look for the standard library’s string module located on the module search path. Moreover, we cannot resolve this with full package import paths, because we cannot depend on any extra package directory structure above the standard library being present on every machine.
In other words, simple imports in packages can be both ambiguous and error-prone. Within a package, it’s not clear whether an import spam statement refers to a module within or outside the package. As one consequence, a local module or package can hide another hanging directly off of sys.path, whether intentionally or not.
In practice, Python users can avoid reusing the names of standard library modules they need for modules of their own (if you need the standard string, don’t name a new module string!). But this doesn’t help if a package accidentally hides a standard module; moreover, Python might add a new standard library module in the future that has the same name as a module of your own. Code that relies on relative imports is also less easy to understand, because the reader may be confused about which module is intended to be used. It’s better if the resolution can be made explicit in code.
To address this dilemma, imports run within packages have changed in Python 3.X to be absolute-only (and can be made so as an option in 2.X). Under this model, an import statement of the following form in our example file mypkg/main.py will always find a string module outside the package, via an absolute import search of sys.path:
import string # Imports string outside package (absolute)
A from import without leading-dot syntax is considered absolute as well:
from string import name # Imports name from string outside package
If you really want to import a module from your package without giving its full path from the package root, though, relative imports are still possible if you use the dot syntax in the from statement:
from . import string # Imports mypkg.string here (relative)
This form imports the string module relative to the current package only and is the relative equivalent to the prior import example’s absolute form (both load a module as a whole). When this special relative syntax is used, the package’s directory is the only directory searched.
We can also copy specific names from a module with relative syntax:
from .string import name1, name2 # Imports names from mypkg.string
This statement again refers to the string module relative to the current package. If this code appears in our mypkg.main module, for example, it will import name1 and name2 from mypkg.string.
In effect, the “.” in a relative import is taken to stand for the package directory containing the file in which the import appears. An additional leading dot performs the relative import starting from the parent of the current package. For example, this statement:
from .. import spam # Imports a sibling of mypkg
will load a sibling of mypkg—i.e., the spam module located in the package’s own container directory, next to mypkg. More generally, code located in some module A.B.C can use any of these forms:
from . import D # Imports A.B.D (. means A.B) from .. import E # Imports A.E (.. means A) from .D import X # Imports A.B.D.X (. means A.B) from ..E import X # Imports A.E.X (.. means A)
Alternatively, a file can sometimes name its own package explicitly in an absolute import statement, relative to a directory on sys.path. For example, in the following, mypkg will be found in an absolute directory on sys.path:
from mypkg import string # Imports mypkg.string (absolute)
However, this relies on both the configuration and the order of the module search path settings, while relative import dot syntax does not. In fact, this form requires that the directory immediately containing mypkg be included in the module search path. It probably is if mypkg is the package root (or else the package couldn’t be used from the outside in the first place!), but this directory may be nested in a much larger package tree. If mypkg isn’t the package’s root, absolute import statements must list all the directories below the package’s root entry in sys.path when naming packages explicitly like this:
from system.section.mypkg import string # system container on sys.path only
In large or deep packages, that could be substantially more work to code than a dot:
from . import string # Relative import syntax
With this latter form, the containing package is searched automatically, regardless of the search path settings, search path order, and directory nesting. On the other hand, the full-path absolute form will work regardless of how the file is being used—as part of a program or package—as we’ll explore ahead.
Relative imports can seem a bit perplexing on first encounter, but it helps if you remember a few key points about them:
Relative imports apply to imports within packages only. Keep in mind that this feature’s module search path change applies only to import statements within module files used as part of a package—that is, intrapackage imports. Normal imports in files not used as part of a package still work exactly as described earlier, automatically searching the directory containing the top-level script first.
Relative imports apply to the from statement only. Also remember that this feature’s new syntax applies only to from statements, not import statements. It’s detected by the fact that the module name in a from begins with one or more dots (periods). Module names that contain embedded dots but don’t have a leading dot are package imports, not relative imports.
In other words, package relative imports in 3.X really boil down to just the removal of 2.X’s inclusive search path behavior for packages, along with the addition of special from syntax to explicitly request that relative package-only behavior be used. If you coded your package imports in the past so that they did not depend upon 2.X’s 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, or full absolute paths.
With packages and relative imports, the module search story in Python 3.X that we have seen so far can be summarized as follows:
Basic modules with simple names (e.g., A) are located 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 described in Chapter 22.
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 and from 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.
Python 2.X works the same, except that normal imports without dots also automatically search the package directory first before proceeding on to sys.path.
In sum, Python imports select between relative (in the containing directory) and absolute (in a directory on sys.path) resolutions as follows:
from . import mAre relative-only in both 2.X and 3.X
import m, from m import xAre relative-then-absolute in 2.X, and absolute-only in 3.X
As we’ll see later, Python 3.3 adds another flavor to modules—namespace packages—which is largely disjointed from the package-relative story we’re covering here. This newer model supports package-relative imports too, and is simply a different way to construct a package. It augments the import search procedure to allow package content to be spread across multiple simple directories as a last-resort resolution. Thereafter, though, the composite package behaves the same in terms of relative import rules.
But enough theory: let’s run some simple code to demonstrate the concepts behind relative imports.
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:\code>c:\Python33\python>>>import string>>>string<module 'string' from 'C:\\Python33\\lib\\string.py'>
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):
# code\string.py print('string' * 8) C:\code>c:\Python33\python>>>import stringstringstringstringstringstringstringstringstring >>>string<module 'string' from '.\\string.py'>
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, package 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
SystemError: Parent module '' not loaded, cannot perform relative import
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:
# code\main.py
import string # Same code but in a file
print(string)
C:\code> C:\python33\python main.py # Equivalent results in 2.X
stringstringstringstringstringstringstringstring
<module 'string' from 'c:\\code\\string.py'>
Similarly, a from . import string in this nonpackage file fails the same as it does at the interactive prompt—programs and packages are different file usage modes.
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. Package roots in this section are located in the CWD added automatically to sys.path, so we don’t need to set PYTHONPATH. I’ll also largely omit empty __init__.py files and most error message text for space (and non-Windows readers will have to pardon the shell commands here, and translate for your platform):
C:\code>del string*# del __pycache__\string* for bytecode in 3.2+ C:\code>mkdir pkgc:\code>notepad pkg\__init__.py# code\pkg\spam.py import eggs # <== Works in 2.X but not 3.X! print(eggs.X) # code\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 is taken to be relative in 2.X but absolute in 3.X, it fails in the latter. That is, 2.X searches the containing package first, but 3.X does not. This is the incompatible behavior you have to be aware of in 3.X:
C:\code>c:\Python27\python>>>import pkg.spam<module 'string' from 'C:\Python27\lib\string.pyc'> 99999 C:\code>c:\Python33\python>>>import pkg.spamImportError: No module named 'eggs'
To make this work in both 2.X and 3.X, change the first file to use the special relative import syntax, so that its import searches the package directory in 3.X too:
# code\pkg\spam.py from . import eggs # <== Use package relative import in 2.X or 3.X print(eggs.X) # code\pkg\eggs.py X = 99999 import string print(string) C:\code>c:\Python27\python>>>import pkg.spam<module 'string' from 'C:\Python27\lib\string.pyc'> 99999 C:\code>c:\Python33\python>>>import pkg.spam<module 'string' from 'C:\\Python33\\lib\\string.py'> 99999
Notice in the preceding example that the package modules still have access to standard library modules like string—their normal imports are still relative to the entries on the module search path. In fact, if you add a string module to the CWD again, imports in a package will find it there instead of in the standard library. Although you can skip the package directory with an absolute import in 3.X, you still can’t skip the home directory of the program that imports the package:
# code\string.py print('string' * 8) # code\pkg\spam.py from . import eggs print(eggs.X) # code\pkg\eggs.py X = 99999 import string # <== Gets string in CWD, not Python lib! print(string) C:\code>c:\Python33\python# Same result in 2.X >>>import pkg.spamstringstringstringstringstringstringstringstring <module 'string' from '.\\string.py'> 99999
To show how this applies to imports of standard library modules, reset the package again. Get rid of the local string module, and define a new one inside the package itself:
C:\code> del string* # del __pycache__\string* for bytecode in 3.2+
# code\pkg\spam.py
import string # <== Relative in 2.X, absolute in 3.X
print(string)
# code\pkg\string.py
print('Ni' * 8)
Now, which version of the string module you get depends on which Python you use. As before, 3.X interprets the import in the first file as absolute and skips the package, but 2.X does not—another example of the incompatible behavior in 3.X:
C:\code>c:\Python33\python>>>import pkg.spam<module 'string' from 'C:\\Python33\\lib\\string.py'> C:\code>c:\Python27\python>>>import pkg.spamNiNiNiNiNiNiNiNi <module 'pkg.string' from 'pkg\string.py'>
Using relative import syntax in 3.X forces the package to be searched again, as it is in 2.X—by using absolute or relative import syntax in 3.X, you can either skip or select the package directory explicitly. In fact, this is the use case that the 3.X model addresses:
# code\pkg\spam.py from . import string # <== Relative in both 2.X and 3.X print(string) # code\pkg\string.py print('Ni' * 8) C:\code>c:\Python33\python>>>import pkg.spamNiNiNiNiNiNiNiNi <module 'pkg.string' from '.\\pkg\\string.py'> C:\code>c:\Python27\python>>>import pkg.spamNiNiNiNiNiNiNiNi <module 'pkg.string' from 'pkg\string.py'>
It’s also important to note that relative import syntax is really a binding declaration, not just a preference. If we delete the string.py file and any associated byte code in this example now, the relative import in spam.py fails in both 3.X and 2.X, instead of falling back on the standard library (or any other) version of this module:
# code\pkg\spam.py from . import string # <== Fails in both 2.X and 3.X if no string.py here! C:\code>del pkg\string*C:\code>C:\python33\python>>>import pkg.spamImportError: cannot import name string C:\code>C:\python27\python>>>import pkg.spamImportError: cannot import name string
Modules referenced by relative imports must exist in the package directory.
Although absolute imports let you skip package modules this way, they still rely on other components of sys.path. For one last test, let’s define two string modules of our own. In the following, there is one module by that name in the CWD, one in the package, and another in the standard library:
# code\string.py print('string' * 8) # code\pkg\spam.py from . import string # <== Relative in both 2.X and 3.X print(string) # code\pkg\string.py print('Ni' * 8)
When we import the string module with relative import syntax like this, we get the version in the package in both 2.X and 3.X, as desired:
C:\code>c:\Python33\python# Same result in 2.X >>>import pkg.spamNiNiNiNiNiNiNiNi <module 'pkg.string' from '.\\pkg\\string.py'>
When absolute syntax is used, though, the module we get varies per version again. 2.X interprets this as relative to the package first, but 3.X makes it “absolute,” which in this case really just means it skips the package and loads the version relative to the CWD—not the version in the standard library:
# code\string.py print('string' * 8) # code\pkg\spam.py import string # <== Relative in 2.X, "absolute" in 3.X: CWD! print(string) # code\pkg\string.py print('Ni' * 8) C:\code>c:\Python33\python>>>import pkg.spamstringstringstringstringstringstringstringstring <module 'string' from '.\\string.py'> C:\code>c:\Python27\python>>>import pkg.spamNiNiNiNiNiNiNiNi <module 'pkg.string' from 'pkg\string.pyc'>
As you can see, although packages can explicitly request modules within their own directories with dots, their “absolute” imports are otherwise still relative to the rest of the normal module search path. In this case, a file in the program using the package hides the standard library module the package may want. The change in 3.X simply allows package code to select files either inside or outside the package (i.e., relatively or absolutely). Because import resolution can depend on an enclosing context that may not be foreseen, though, absolute imports in 3.X are not a guarantee of finding a module in the standard library.
Experiment with these examples on your own for more insight. In practice, this is not usually as ad hoc as it might seem: you can generally structure your imports, search paths, and module names to work the way you wish during development. You should keep in mind, though, that imports in larger systems may depend upon context of use, and the module import protocol is part of a successful library’s design.
Now that you’ve learned about package-relative imports, you should also keep in mind that they may not always be your best option. Absolute package imports, with a complete directory path relative to a directory on sys.path, are still sometimes preferred over both implicit package-relative imports in Python 2.X, and explicit package-relative import dot syntax in both Python 2.X and 3.X. This issue may seem obscure, but will likely become important fairly soon after you start coding packages of your own.
As we’ve seen, Python 3.X’s relative import syntax and absolute search rule default make intrapackage imports explicit and thus easier to notice and maintain, and allow explicit choice in some name conflict scenarios. However, there are also two major ramifications of this model that you should be aware of:
In both Python 3.X and 2.X, use of package-relative import statements implicitly binds a file to a package directory and role, and precludes it from being used in other ways.
In Python 3.X, the new relative search rule change means that a file can no longer serve as both script and package module as easily as it could in 2.X.
These constraint’s causes are a bit subtle, but because the following are simultaneously true:
Python 3.X and 2.X do not allow from . relative syntax to be used unless the importer is being used as part of a package (i.e., is being imported from somewhere else).
Python 3.X does not search a package module’s own directory for imports, unless from . relative syntax is used (or the module is in the current working directory or main script’s home directory).
Use of relative imports prevents you from creating directories that serve as both executable programs and externally importable packages in 3.X and 2.X. Moreover, some files can no longer serve as both script and package module in 3.X as they could in 2.X. In terms of import statements, the rules pan out as follows—the first is for package mode only in both Pythons, and the second is for program mode only in 3.X:
from . import mod # Not allowed in nonpackage mode in both 2.X and 3.X import mod # Does not search file's own directory in package mode in 3.X
The net effect is that for files to be used in either 2.X or 3.X, you may need to choose a single usage mode—package (with relative imports) or program (with simple imports), and isolate true package module files in a subdirectory apart from top-level script files.
Alternatively, you can attempt manual sys.path changes (a generally brittle and error-prone task), or always use full package paths in absolute imports instead of either package-relative syntax or simple imports, and assume the package root is on the module search path:
from system.section.mypkg import mod # Works in both program and package mode
Of all these schemes, the last—full package path imports—may be the most portable and functional, but we need to turn to more concrete code to see why.
For example, in Python 2.X it’s common to use the same single directory as both program and package, using normal undotted imports. This relies on the script’s home directory to resolve imports when used as a program, and the 2.X relative-then-absolute rule to resolve intrapackage imports when used as a package. This won’t quite work in 3.X, though—in package mode, plain imports do not load modules in the same directory anymore, unless that directory also happens to be the same as the main file’s container or the current working directory (and hence, be on sys.path).
Here’s what this looks like in action, stripped to a bare minimum of code (for brevity in this section I again omit __init__.py package directory files required prior to Python 3.3, and for variety use the 3.3 Windows launcher covered in Appendix B):
# code\pkg\main.py import spam # code\pkg\spam.py import eggs # <== Works if in "." = home of main script file # code\pkg\eggs.py print('Eggs' * 4) # But won't load this file when used as pkg in 3.X! c:\code>python pkg\main.py# OK as program, in both 2.X and 3.X EggsEggsEggsEggs c:\code>python pkg\spam.pyEggsEggsEggsEggs c:\code>py −2# OK as package in 2.X: relative-then-absolute >>>import pkg.spam# 2.X: plain imports search package directory first EggsEggsEggsEggs C:\code>py −3# But 3.X fails to find file here: absolute only >>>import pkg.spam# 3.X: plain imports search only CWD plus sys.path ImportError: No module named 'eggs'
Your next step might be to add the required relative import syntax for 3.X use, but it won’t help here. The following retains the single directory for both a main top-level script and package modules, and adds the required dots—in both 2.X and 3.X this now works when the directory is imported as a package, but fails when it is used as a program directory (including attempts to run a module as a script directly):
# code\pkg\main.py import spam # code\pkg\spam.py from . import eggs # <== Not a package if main file here (even if me)! # code\pkg\eggs.py print('Eggs' * 4) c:\code>python# OK as package but not program in both 3.X and 2.X >>>import pkg.spamEggsEggsEggsEggs c:\code>python pkg\main.pySystemError: ... cannot perform relative import c:\code>python pkg\spam.pySystemError: ... cannot perform relative import
In a mixed-use case like this, one solution is to isolate all but the main files used only by the program in a subdirectory—this way, your intrapackage imports still work in all Pythons, you can use the top directory as a standalone program, and the nested directory still serves as a package for use from other programs:
# code\pkg\main.py import sub.spam # <== Works if move modules to pkg below main file # code\pkg\sub\spam.py from . import eggs # Package relative works now: in subdirectory # code\pkg\sub\eggs.py print('Eggs' * 4) c:\code>python pkg\main.py# From main script: same result in 2.X and 3.X EggsEggsEggsEggs c:\code>python# From elsewhere: same result in 2.X and 3.X >>>import pkg.sub.spamEggsEggsEggsEggs
The potential downside of this scheme is that you won’t be able to run package modules directly to test them with embedded self-test code, though tests can be coded separately in their parent directory instead:
c:\code> py −3 pkg\sub\spam.py # But individual modules can't be run to test
SystemError: ... cannot perform relative import
Alternatively, full path package import syntax would address this case too—it requires the directory above the package root to be in your path, though this is probably not an extra requirement for a realistic software package. Most Python packages will either require this setting, or arrange for it to be handled automatically with install tools (such as distutils, which may store a package’s code in a directory on the default module search path such as the site-packages root; see Chapter 22 for more details):
# code\pkg\main.py import spam # code\pkg\spam.py import pkg.eggs # <== Full package paths work in all cases, 2.X+3.X # code\pkg\eggs.py print('Eggs' * 4) c:\code>set PYTHONPATH=C:\codec:\code>python pkg\main.py# From main script: Same result in 2.X and 3.X EggsEggsEggsEggs c:\code>python# From elsewhere: Same result in 2.X and 3.X >>>import pkg.spamEggsEggsEggsEggs
Unlike the subdirectory fix, full path absolute imports like these also allow you to run your modules standalone to test:
c:\code> python pkg\spam.py # Individual modules are runnable too in 2.X and 3.X
EggsEggsEggsEggs
To summarize, here’s another typical example of the issue and its full path resolution. This uses a common technique we’ll expand on in the next chapter, but the idea is simple enough to include as a preview here (though you may want to review this again later—the coverage makes more sense here).
Consider the following two modules in a package directory, the second of which includes self-test code. In short, a module’s __name__ attribute is the string “__main__” when it is being run as a top-level script, but not when it is being imported, which allows it to be used as both module and script:
# code\dualpkg\m1.py
def somefunc():
print('m1.somefunc')
# code\dualpkg\m2.py
...import m1 here... # Replace me with a real import statement
def somefunc():
m1.somefunc()
print('m2.somefunc')
if __name__ == '__main__':
somefunc() # Self-test or top-level script usage mode code
The second of these needs to import the first where the “...import m1 here...” placeholder appears. Replacing this line with a relative import statement works when the file is used as a package, but is not allowed in nonpackage mode by either 2.X or 3.X (results and error messages are omitted here for space; see the file dualpkg\results.txt in the book’s examples for the full listing):
# code\dualpkg\m2.py from . import m1 c:\code>py −3>>>import dualpkg.m2# OK C:\code>py −2>>>import dualpkg.m2# OK c:\code>py −3 dualpkg\m2.py# Fails! c:\code>py −2 dualpkg\m2.py# Fails!
Conversely, a simple import statement works in nonpackage mode in both 2.X and 3.X, but fails in package mode in 3.X only, because such statements do not search the package directory in 3.X:
# code\dualpkg\m2.py import m1 c:\code>py −3>>>import dualpkg.m2# Fails! c:\code>py −2>>>import dualpkg.m2# OK c:\code>py −3 dualpkg\m2.py# OK c:\code>py −2 dualpkg\m2.py# OK
And finally, using full package paths works again in both usage modes and Pythons, as long as the package’s root is on the module search path (as it must be to be used elsewhere):
# code\dualpkg\m2.py import dualpkg.m1 as m1 # And: set PYTHONPATH=c:\code c:\code>py −3>>>import dualpkg.m2# OK C:\code>py −2>>>import dualpkg.m2# OK c:\code>py −3 dualpkg\m2.py# OK c:\code>py −2 dualpkg\m2.py# OK
In sum, unless you’re willing and able to isolate your modules in subdirectories below scripts, full package path imports are probably preferable to package-relative imports—though they’re more typing, they handle all cases, and they work the same in 2.X and 3.X. There may be additional workarounds that involve extra tasks (e.g., manually setting sys.path in your code), but we’ll skip them here because they are more obscure and rely on import semantics, which is error-prone; full package imports rely only on the basic package mechanism.
Naturally, the extent to which this may impact your modules can vary per package; absolute imports may also require changes when directories are reorganized, and relative imports may become invalid if a local module is relocated.
Be sure to also watch for future Python changes on this front. Although this book covers Python up to 3.3 only, at this writing, there is talk in a PEP of possibly addressing some package issues in Python 3.4, perhaps even allowing relative imports to be used in program mode. On the other hand, this initiative’s scope and outcome is uncertain and would work only on 3.4 and later; the full path solution given here is version-neutral; and 3.4 is more than a year away in any event. That is, you can wait for a change to a 3.X change that limited functionality, or simply use tried-and-true full package paths.