__init__.py: what in the world is it for?

It’s very common when looking into python code, to see some __inti__.py files around. Most of the times you will see them empty, many times you will se imports or more generic stuff and sometimes a bunch of code in there. If you for example check some django code, say models, you’ll see more than you would initially expect. So, what exactly is __init__.py for? Let’s check the docs:

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.

What does this mean exactly? Well, if a directory has an __init__.py Python will know that it will treat it as a package. This way  the different modules within your package can be imported in a similar manner as plain modules.

Leaving the this file empty is common, and viewed by many as a good practice, if your packages  modules and sub-packages have no need to share any code. A common practice is to import selected classes, functions, etc into package level making them imported directly from the package.  Also common is to to make subpackages and modules available by using the __all__ variable. When this variable is present, the interpreter imports all the modules listed there.

Sometimes, as shown in the above django example, __init__.py can contain a lot more code. The first time you import any module from that package, the code inside __init__.py runs. It’s up to you to decide what it’s worth to be package level or not. A recurrent issue in including to much code in __init__.py is when the complexity of a project grows, threre might be several sub packages in a deep and complex directory structure. What this means is that importing a single item  will require executing all __init__.py files found while transversing the structure.

As you can see __init__.py plays an import role in Python. You can read more about packages and modules in the official documentation for Modules.