Why would I put code in __init__.py files?

PythonModule

Python Problem Overview


I am looking for what type of code would I put in __init__.py files and what are the best practices related to this. Or, is it a bad practice in general ?

Any reference to known documents that explain this is also very much appreciated.

Python Solutions


Solution 1 - Python

Libraries and frameworks usually use initialization code in __init__.py files to neatly hide internal structure and provide a uniform interface to the user.

Let's take the example of Django forms module. Various functions and classes in forms module are defined in different files based on their classification.

forms/
  __init__.py
  extras/
    ...
  fields.py
  forms.py
  widgets.py
  ...

Now if you were to create a form, you would have to know in which file each function is defined and your code to create a contact form will have to look something like this (which is incovenient and ugly).

 class CommentForm(forms.forms.Form):
    name = forms.fields.CharField() 
    url = forms.fields.URLField()
    comment = forms.fields.CharField(widget=forms.widgets.Textarea) 

Instead, in Django you can just refer to various widgets, forms, fields etc. directly from the forms namespace.

from django import forms

class CommentForm(forms.Form):
    name = forms.CharField()
    url = forms.URLField()
    comment = forms.CharField(widget=forms.Textarea)

How is this possible? To make this possible, Django adds the following statement to forms/__init__.py file which import all the widgets, forms, fields etc. into the forms namespace.

from widgets import *
from fields import *
from forms import *
from models import *

As you can see, this simplifies your life when creating the forms because now you don't have to worry about in where each function/class is defined and just use all of these directly from forms namespace. This is just one example but you can see examples like these in other frameworks and libraries.

Solution 2 - Python

One of the best practices in that area is to import all needed classes from your library (look at mongoengine, for example). So, a user of your library can do this:

from coollibrary import OneClass, SecondClass

instead of

from coollibrary.package import OneClass
from coollibrary.anotherpackage import SecondClass

Also, good practice is include in __init__.py version constant

Solution 3 - Python

  1. For convenience: The other users will not need to know your functions' exactly location.

     your_package/
       __init__.py
       file1.py/
       file2.py/
         ...
       fileN.py
    
     # in __init__.py
     from file1 import *
     from file2 import *
     ...
     from fileN import *
    
     # in file1.py
     def add():
         pass
    

    then others can call add() by

     from your_package import add
    

    without knowing file1, like

     from your_package.file1 import add
    
  2. Put something for initializing. For example, the logging(this should put in the top level):

     import logging.config
     logging.config.dictConfig(Your_logging_config)
    

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwebDevelSouthView Question on Stackoverflow
Solution 1 - PythonPraveen GollakotaView Answer on Stackoverflow
Solution 2 - PythondarvinView Answer on Stackoverflow
Solution 3 - PythonflyceeView Answer on Stackoverflow