85

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.

1

3 Answers 3

71

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.

1
14

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

1
  • 1
    What do you mean by version constant ? Could you please clear this statement out ?
    – thanos.a
    Commented Jan 5, 2021 at 17:03
7
  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)
    

Not the answer you're looking for? Browse other questions tagged or ask your own question.