Lets say you have a structure of files that looks like this:
/python/
/python/start_server.py
/python/server/
/python/server/__init__.py
/python/server/request_handler.py - Lets say we define a RequestHandler class in here.
/python/server/conn/
/python/server/conn/__init__.py
/python/server/conn/listener.py - Lets say we define a Listener class in here.
The first directory python
is optional. I used it in this example in
case you had a multiple project or multiple language checkout and wanted to
keep your python bits separate.
If this is not the case you can pretend like the python dir doesn't exist at all and this should still work out the same.
Our code starts inside of the python
directory so this will be the root
of this project.
The subdirectories naturally make python modules
. So from python's point of view
we have the following modules.
server
server.request_handler
server.conn
server.conn.listener
We have the following classes.
server.request_handler.RequestHandler
server.conn.listener.Listener
In start_server.py
I might do something like:
from server.conn.listener import Listener
if __name__ == '__main__':
Listener().start_listening()
Keep this in mind as we go further.
Think of when you are creating a class and if you want your object
to execute some code at the beginning you put the code in the __init__
method.
For example, the Listener class almost certainly has a method called __init__(self)
and it gets
called when we instantiate Listener.
The __init__.py
files are essentially the same thing except for modules.
Imagine if the server.conn
module was a class. Its __init__(self)
would be the /python/server/conn/__init__.py
file instead.
These files can (and frequently are) completely empty. But here is an example of how they work.
If I were to add to the file /python/server/conn/__init__.py
the following code:
some_kind_of_variable = 'Yahoo!'
In other code I could do this:
from server.conn import some_kind_of_variable
print(some_kind_of_variable)
By mentioning 'server.conn' it was like instantiating that module and everything within /python/server/conn/__init__.py
was executed
within that module's scope. Since we created a variable some_kind_of_variable
it is now available within that module.
We could also do:
print(server.conn.some_kind_of_variable)
Any time you are one or more subdirectories in from the base of the python project and you intend to import python code from there.
In the initial example we had an additional /python
folder that wasn't part of the project so it did not need an __init__.py
file in it.
We did, however, intend to import from server
, so it needed to have a __init__.py
file in it.
Here is another example of paths with examples of where NOT to use __init__.py
. In this case our code is intended to be
ran from the root instead of a separate python
directory.
/start_the_importer.py
/core/
/core/__init__.py
/core/file_handling.py
/importer/
/importer/__init__.py
/importer/the_icky_file_importer.py
/tests/
/tests/__init__.py
/tests/core/
/tests/core/__init__.py
/tests/core/test_file_handling.py
/tests/importer/
/tests/importer/__init__.py
/tests/importer/test_the_icky_file_importer.py
/docs/
/docs/README.md
/html/
/html/status_page.html
You will note that there is NOT a /__init__.py
file. Since this is the base of the python code, we are not yet in a module
and so we don't need an __init__.py
file.
We do intend to import code from core
and importer
and tests
and tests.core
and tests.importer
. All of
those folders get their own __init__.py
files. In these cases, those files are completely empty.
This allows python to see that it can import from these modules but the modules themselves don't need any special code.
Last, you will notice that /docs
and /html
do not continain __init__.py
files. That is because they are not intended
to be python modules and therefore don't need them.