Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 55e6cd3

Browse filesBrowse files
author
Kenneth Reitz
committed
Merge pull request realpython#127 from guibog/master
On modules and packages
2 parents 5a67084 + 8ad935e commit 55e6cd3
Copy full SHA for 55e6cd3

File tree

Expand file treeCollapse file tree

1 file changed

+112
-0
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+112
-0
lines changed

‎docs/writing/structure.rst

Copy file name to clipboardExpand all lines: docs/writing/structure.rst
+112Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,120 @@ include:
5757
task at hand, you might be swimming in ravioli code.
5858

5959

60+
Modules
61+
-------
62+
63+
Python modules are one of the main abstraction layer available and probably the
64+
most natural one. Abstraction layers allow separating code into parts holding
65+
related data and functionalities.
66+
67+
For example, a layer of a project can handle interfacing with user actions,
68+
while another would handle low-level manipulation of data. The most natural way
69+
to separate these two layers is to regroup all interfacing functionalities
70+
in one file, and all low-level operations in another file. In this case,
71+
the interface file need to import the low-level file. This is done with the
72+
`import` and `from ... import` statements.
73+
74+
As soon as you use `import` statements you use modules, either builtin modules
75+
such as `os` and `sys`, or third-party modules you have installed in your
76+
environment, or project's internal modules.
77+
78+
Nothing special is required for a Python file to be a module, but the import
79+
mechanism need to be understood in order to use this concept properly and avoid
80+
some issues.
81+
82+
Concretely, the `import modu` statement will look for the proper file, which is
83+
`modu.py` in the same directory as the caller if it exists. If it is not
84+
found, the Python interpreter with search for `modu.py` in the "path"
85+
recursively and raise an ImportError exception if it is not found.
86+
87+
Once `modu.py` is found, the Python interpreter will execute the module in an
88+
isolated scope. Any top-level statement in `modu.py` will be executed,
89+
including other imports if any. Function and classes definitions are stored in
90+
the module's dictionary.
91+
92+
Then modules variables, functions and classes will be available to the caller
93+
through the module's namespace, a central concept in programming that is
94+
particularly helpful and powerful in Python.
95+
96+
In many languages, a `include file` directive is used by the preprocessor to
97+
take all code found in the file and 'copy' it in the caller's code. It is
98+
different in Python: the included code is isolated in a module namespace, which
99+
means that you generally don't have to worry that the included code could have
100+
unwanted effect, eg override an existing function with the same name.
101+
102+
It is possible to simulate the more standard behavior by using a special syntax
103+
of the import statement: `from modu import *`. This is generally considered bad
104+
practice, **using import * makes code harder to read and dependencies less
105+
compartimented**.
106+
107+
Using `from modu import func` is a way to pinpoint the function you want to
108+
import and put it is the global namespace. While much less harmful than `import
109+
*` because it shows explicitely what is imported in the global namespace, it's
110+
advantage over a simpler `import modu` is only that it will save some typing.
111+
112+
**Very bad**
113+
114+
.. code-block:: python
115+
116+
[...]
117+
from modu import *
118+
[...]
119+
x = sqrt(4) # Is sqrt part of modu? A builtin? Defined above?
120+
121+
**Better**
122+
123+
.. code-block:: python
124+
125+
from modu import sqrt
126+
[...]
127+
x = sqrt(4) # sqrt may be part of modu, if not redefined in between
128+
129+
**Best**
130+
131+
.. code-block:: python
132+
133+
import modu
134+
[...]
135+
x = modu.sqrt(4) # sqrt is visibly part of modu's namespace
136+
137+
As said in the section about style, readability is one of the main feature of
138+
Python. Readability means to avoid useless boilerplate text and clutter,
139+
therefore some efforts are spent trying to achieve a certain level of brevity.
140+
But terseness and obscurity are the limits where brevity should stop: being
141+
able to tell immediately from where comes a class or a function, as in the
142+
`modu.func` idiom, improves greatly code readability and understandability in
143+
most cases but the simplest single file projects.
144+
145+
146+
Packages --------
147+
148+
Python provides a very straightforward packaging system, which is simply an
149+
extension of the module mechanism to a directory.
150+
151+
Any directory with a __init__.py file is considered a Python package. The
152+
different modules in the package are imported in a similar manner as plain
153+
modules, will a special behavior for the __init__.py file, that is used to
154+
gather all package-wide definitions.
155+
156+
A file modu.py in the directory pack/ is imported with the statement `import
157+
pack.modu`. This statement will look for a __init__.py file in `pack`, execute
158+
all its top-level statements. Then it will look for a file `pack/modu.py` and
159+
execute all its top-level statements. After these operations, any variable,
160+
function or class defined in modu.py is available in pack.modu namespace.
161+
162+
A commonly seen issue is to add too many code and functions in __init__.py
163+
files. When the project complexity grows, there may be sub-packages and
164+
sub-sub-packages in a deep directory structure, and then, import a single item
165+
from a sub-sub-package will require to execute all __init__.py file met while
166+
descending the tree.
60167

168+
Leaving a __init__.py file empty is considered normal and even a good pratice,
169+
if the package's modules and sub-packages do not need to share any code.
61170

171+
Lastly, a convenient syntax is available for importing deeply nested packages:
172+
`import very.deep.module as mod` allow to use `mod` in place of the verbose
173+
repetition of `very.deep.module` in front of each calls to module items.
62174

63175
Vendorizing Dependencies
64176
------------------------

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.