Python imports documentation edits

This commit is contained in:
William S Fulton 2013-12-24 14:39:25 +00:00
commit 91120c84f2

View file

@ -108,7 +108,7 @@
<ul>
<li><a href="#Python_modulepackage">%module(package="...") syntax</a>
<li><a href="#Python_absrelimports">Absolute and relative imports</a></li>
<li><a href="Python_absimport">Enforcing absolute import semantics</a></li>
<li><a href="#Python_absimport">Enforcing absolute import semantics</a></li>
<li><a href="#Python_importfrominit">Importing from __init__.py</a></li>
</ul>
<li><a href="#Python_python3support">Python 3 Support</a>
@ -5284,11 +5284,11 @@ code and may be grouped together to form a package. Packages may be nested,
that is they may contain subpackages. This leads to tree-like hierarchy, with
packages as intermediate nodes and modules as leaf nodes.</p>
<p>The hierarchy of python packages/modules follows the hierarchy of
<tt>*.py</tt> files found in source tree (or, more generally, in python path).
<p>The hierarchy of Python packages/modules follows the hierarchy of
<tt>*.py</tt> files found in a source tree (or, more generally, in the Python path).
Normally, the developer creates new module by placing a <tt>*.py</tt> file
somewhere under python path; the module is then named after that <tt>*.py</tt>
file. A package is created by placing <tt>__init__.py</tt> file within a
somewhere under Python path; the module is then named after that <tt>*.py</tt>
file. A package is created by placing an <tt>__init__.py</tt> file within a
directory; the package is then named after that directory. For example, the
following source tree:</p>
@ -5303,7 +5303,7 @@ pkg1/pkg2/mod3.py
</div>
<p>
defines the following python packages and modules:
defines the following Python packages and modules:
</p>
<div class="diagram">
@ -5317,28 +5317,28 @@ pkg1.pkg2.mod3 # module
</div>
<p>
The purpose of <tt>__init__.py</tt> file is two-fold. First, existence of
<tt>__init__.py</tt> in a directory informs python interpreter that this
directory contains python package. Second, the code of <tt>__init__.py</tt> is
The purpose of an <tt>__init__.py</tt> file is two-fold. First, the existence of
<tt>__init__.py</tt> in a directory informs the Python interpreter that this
directory contains a Python package. Second, the code in <tt>__init__.py</tt> is
loaded/executed automatically when the package is initialized (when it or its
submodule/subpackage gets <tt>import</tt>'ed). By default, swig generates
proxy python code &ndash; one <tt>*.py</tt> file for each <tt>*.i</tt>
interface. The <tt>__init__.py</tt> files, however, are not generated by swig.
submodule/subpackage gets <tt>import</tt>'ed). By default, SWIG generates
proxy Python code &ndash; one <tt>*.py</tt> file for each <tt>*.i</tt>
interface. The <tt>__init__.py</tt> files, however, are not generated by SWIG.
They should be created by other means. Both files (module <tt>*.py</tt> and
<tt>__init__.py</tt>) should be installed in appropriate destination
directories in order to obtain desirable package/module hierarchy.
directories in order to obtain a desirable package/module hierarchy.
</p>
<p>The way python defines its modules and packages impacts swig users. Some
users may need to use special features such as <tt>package</tt> option of
<tt>%module</tt> directive or import-related command-line options. These are
<p>The way Python defines its modules and packages impacts SWIG users. Some
users may need to use special features such as the <tt>package</tt> option in the
<tt>%module</tt> directive or import related command line options. These are
explained in the following sections.</p>
<H3><a name="Python_modulepackage"></a>34.11.1 %module(package="...") syntax</H3>
<H3><a name="Python_modulepackage"></a>34.11.1 Setting the Python package</H3>
<p>
Using the <tt>package</tt> option of the <tt>%module</tt> directive allows you
to specify a Python package that the module will be living in when installed.
Using the <tt>package</tt> option in the <tt>%module</tt> directive allows you
to specify a Python package that the module will be in when installed.
</p>
<div class="code">
@ -5351,20 +5351,20 @@ to specify a Python package that the module will be living in when installed.
This is useful when the <tt>.i</tt> file is <tt>%import</tt>ed by
another <tt>.i</tt> file. By default SWIG will assume that the
importer is able to find the importee with just the module name, but
if they live in separate Python packages then that won't work.
if they live in separate Python packages then this won't work.
However if the importee specifies what its package is with the
<tt>%module</tt> option then the Python code generated for the
importer will use that package name when importing the other module
and also in base class declarations, etc..
and in base class declarations, etc..
</p>
<p>Swig assumes, that the <tt>package</tt> option provided to <tt>%module</tt>
<p>SWIG assumes that the <tt>package</tt> option provided to <tt>%module</tt>
together with the <tt>module</tt> name (that is, <tt>wx.xrc</tt> in the above
example) forms a fully qualified (absolute) name of a module (in Python terms).
This is important especially for Python 3, where absolute imports are used by
default. It's up to you to place the generated module files (<tt>.py</tt>,
<tt>.so</tt>) in proper subdirectories. For example, if you have
interface <tt>foo.i</tt> with:
<tt>.so</tt>) in appropriate subdirectories. For example, if you have an
interface file <tt>foo.i</tt> with:
</p>
<div class="code">
@ -5374,7 +5374,7 @@ interface <tt>foo.i</tt> with:
</div>
<p>
then the resultant directory layout should be
then the resulting directory layout should be
</p>
<div class="diagram">
@ -5382,8 +5382,8 @@ then the resultant directory layout should be
pkg1/
pkg1/__init__.py
pkg1/pkg2/__init__.py
pkg1/pkg2/foo.py # (generated by swig)
pkg1/pkg2/_foo.so # (shared library from C/C++ code generated by SWIG)
pkg1/pkg2/foo.py # (generated by SWIG)
pkg1/pkg2/_foo.so # (shared library built from C/C++ code generated by SWIG)
</pre>
</div>
@ -5409,9 +5409,9 @@ class M3: pass
</div>
<p>
We edit <tt>pkg1/mod2.py</tt> and want to import module of
We edit <tt>pkg1/mod2.py</tt> and want to import module
<tt>pkg1/pkg2/pkg3.py</tt> in order to derive from class <tt>M3</tt>. We can
write appropriate python code in several ways, for example:
write appropriate Python code in several ways, for example:
</p>
<ol>
@ -5426,7 +5426,7 @@ class M2(pkg1.pkg2.mod3.M3): pass
</li>
<li><p>Using "<tt>import &lt;&gt;</tt>" syntax with package name relative to
<tt>pkg1</tt> (only in python 2.7 and earlier):</p>
<tt>pkg1</tt> (only in Python 2.7 and earlier):</p>
<div class="targetlang">
<pre>
# pkg1/mod2.py
@ -5437,7 +5437,7 @@ class M2(pkg2.mod3.M3): pass
</li>
<li><p>Using "<tt>from &lt;&gt; import &lt;&gt;</tt>" syntax (relative import
syntax, only in python 2.5 and later):</p>
syntax, only in Python 2.5 and later):</p>
<div class="targetlang">
<pre>
# pkg1/mod2.py
@ -5449,7 +5449,7 @@ class M2(mod3.M3): pass
<li><p>Other variants, for example the following construction in order to
have the <tt>pkg2.mod3.M3</tt> symbol available in <tt>mod2</tt> as
in point 2 above (but now under python 3):</p>
in point 2 above (but now under Python 3):</p>
<div class="targetlang">
<pre>
# pkg1/mod2.py
@ -5483,13 +5483,13 @@ class M2(pkg2.mod3.M3): pass
</pre>
</div>
<p>By default, swig would generate <tt>mod2.py</tt> proxy file with
<tt>import</tt> directive as in point 1. This may be changed with
<tt>-relativeimport</tt> CLI option. The <tt>-relativeimport</tt> instructs
swig to organize imports as in point 2 (for python 2.x) or as in point 4 (for
python 3, that is when -py3 CLI option is enabled). In short, if you have
<p>By default, SWIG would generate <tt>mod2.py</tt> proxy file with
<tt>import</tt> directive as in point 1. This can be changed with the
<tt>-relativeimport</tt> command line option. The <tt>-relativeimport</tt> instructs
SWIG to organize imports as in point 2 (for Python 2.x) or as in point 4 (for
Python 3, that is when the -py3 command line option is enabled). In short, if you have
<tt>mod2.i</tt> and <tt>mod3.i</tt> as above, then without
<tt>-relativeimport</tt> swig will write</p>
<tt>-relativeimport</tt> SWIG will write</p>
<div class="targetlang">
<pre>
@ -5515,20 +5515,20 @@ import pkg1.pkg2.mod3
</pre>
</div>
<p>when <tt>-py3</tt> option is used.</p>
<p>when <tt>-py3</tt> is used.</p>
<p>You should avoid using relative imports and use absolute ones whenever
possible. There are some cases, however, when relative imports may be
necessary. The first example is, when some (legacy) python code refers entities
imported by proxy files generated by swig, and it assumes that the proxy file
necessary. The first example is, when some (legacy) Python code refers entities
imported by proxy files generated by SWIG, and it assumes that the proxy file
uses relative imports. Second case is, when one puts import directives in
<tt>__init__.py</tt> to import symbols from submodules or subpackages and the
submodule depends on other submodules (discussed later).</p>
<H3><a name="Python_absimport"></a>34.11.3 Enforcing absolute import semantics</H3>
<p>As you may know, there is incompatibility in import semantics (for the
<tt>import &lt;&gt;</tt> syntax) between python 2 and 3. In python 2.4 and
<p>As you may know, there is an incompatibility in import semantics (for the
<tt>import &lt;&gt;</tt> syntax) between Python 2 and 3. In Python 2.4 and
earlier it is not clear whether</p>
<div class="targetlang">
@ -5537,10 +5537,10 @@ import foo
</pre>
</div>
<p>refers to a top-level module or to another module inside the current
package. In python 3 it always refers to a top-level module
package. In Python 3 it always refers to a top-level module
(see <a href="http://www.python.org/dev/peps/pep-0328/">PEP 328</a>).
To instruct python 2.5 through 2.7 to use new semantics (that is <tt>import
foo</tt> is interpreted as absolute import), one have to put the following
To instruct Python 2.5 through 2.7 to use new semantics (that is <tt>import
foo</tt> is interpreted as absolute import), one has to put the following
line
</p>
@ -5550,26 +5550,26 @@ from __future__ import absolute_import
</pre>
</div>
<p>at the very beginning of his proxy <tt>*.py</tt> file. In swig, it may be
<p>at the very beginning of his proxy <tt>*.py</tt> file. In SWIG, it may be
accomplished with <tt>%pythonbegin</tt> directive.</p>
<H3><a name="Python_importfrominit"></a>34.11.4 Importing from __init__.py</H3>
<p>Imports in <tt>__init__.py</tt> are handy when you want to populate
package's namespace with names imported from other modules. In swig-based
projects this approach may also be used to split large piece of code into
smaller modules, compile them in parallel and then re-assemble all stuff at
python level by importing submodules' contents in <tt>__init__.py</tt>, for
<p>Imports in <tt>__init__.py</tt> are handy when you want to populate a
package's namespace with names imported from other modules. In SWIG based
projects this approach may also be used to split large pieces of code into
smaller modules, compile them in parallel and then re-assemble everything at another
level by importing submodules' contents in <tt>__init__.py</tt>, for
example.</p>
<p>Unfortunately import directives in <tt>__init__.py</tt> may cause troubles,
especially if they refer to package's submodules. This is caused by the way
python initializes packages. If you spot problems with imports from
<p>Unfortunately import directives in <tt>__init__.py</tt> may cause problems,
especially if they refer to a package's submodules. This is caused by the way
Python initializes packages. If you spot problems with imports from
<tt>__init__.py</tt> try using <tt>-relativeimport</tt> option. Below we
explain in detail one issue, for which the <tt>-relativeimport</tt> workaround
may be helpful.</p>
<p>Consider the following example (python 3):</p>
<p>Consider the following example (Python 3):</p>
<div class="diagram">
<pre>
@ -5580,10 +5580,10 @@ pkg1/pkg2/bar.py # (imports foo.py)
</pre>
</div>
<p>Let's the files' contents be:</p>
<p>If the file contents are:</p>
<ul>
<li> <p>for <tt>pkg1/pkg2/__init__.py:</tt></p>
<li> <p><tt>pkg1/pkg2/__init__.py:</tt></p>
<div class="targetlang">
<pre>
# pkg1/pkg2/__init__.py
@ -5592,7 +5592,7 @@ from .bar import Bar
</div>
</li>
<li> <p>for <tt>pkg1/pkg2/foo.py:</tt></p>
<li> <p><tt>pkg1/pkg2/foo.py:</tt></p>
<div class="targetlang">
<pre>
# pkg1/pkg2/foo.py
@ -5601,7 +5601,7 @@ class Foo: pass
</div>
</li>
<li> <p>for <tt>pkg1/pkg2/foo.py:</tt></p>
<li> <p><tt>pkg1/pkg2/bar.py:</tt></p>
<div class="targetlang">
<pre>
# pkg1/pkg2/bar.py
@ -5612,7 +5612,7 @@ class Bar(pkg1.pkg2.foo.Foo): pass
</li>
</ul>
<p>Now one would simply do <tt>import pkg1.pkg2</tt>, but this usually fails:</p>
<p>Now if one simply used <tt>import pkg1.pkg2</tt>, it will usually fail:</p>
<div class="diagram">
<pre>
@ -5628,16 +5628,16 @@ AttributeError: 'module' object has no attribute 'pkg2'
</div>
<p>Surprisingly, if we execute the <tt>import pkg1.pkg2</tt> directive for the
second time, it succeeds. The reason seems to be following: when python spots
second time, it succeeds. The reason seems to be following: when Python spots
the <tt>from .bar import Bar</tt> directive in <tt>pkg1/pkg2/__init__.py</tt>
it starts loading <tt>pkg1/pkg2/bar.py</tt>. This module imports
<tt>pkg1.pkg2.foo</tt> in turn and tries to use <tt>pkg1.pkg2.foo.Foo</tt>, but
the package <tt>pkg1</tt> is not fully initialized yet (the initialization
procedure is actually in progress) and it seems like the effect of already seen
directive <tt>import pkg1.pkg2.pkg3.foo</tt> is "delayed" or ignored. Exactly
same may happen to a proxy module generated by swig.</p>
procedure is actually in progress) and it seems like the effect of the already seen
<tt>import pkg1.pkg2.pkg3.foo</tt> is "delayed" or ignored. Exactly the
same may happen to a proxy module generated by SWIG.</p>
<p>It's observed, that a possible workaround for this case is to use relative
<p>One workaround for this case is to use a relative
import in <tt>pkg1/pkg2/bar.py</tt>. If we change <tt>bar.py</tt> to be:</p>
<div class="targetlang">
@ -5657,9 +5657,9 @@ class Bar(pkg3.foo.Foo): pass
</pre>
</div>
<p>then the example works again. With swig, you need to enable the
<p>then the example works again. With SWIG, you need to enable the
<tt>-relativeimport</tt> option in order to have the above workaround in
effect (note, that python 2 case also needs <tt>-relativeimport</tt>
effect (note, that the Python 2 case also needs the <tt>-relativeimport</tt>
workaround).</p>