Adding code to __init__.py
Asked Answered
N

4

104

I'm taking a look at how the model system in django works and I noticed something that I don't understand.

I know that you create an empty __init__.py file to specify that the current directory is a package. And that you can set some variable in __init__.py so that import * works properly.

But django adds a bunch of from ... import ... statements and defines a bunch of classes in __init__.py. Why? Doesn't this just make things look messy? Is there a reason that requires this code in __init__.py?

Nasa answered 23/9, 2008 at 4:41 Comment(5)
This isn't really about Django is it? Yes, you saw it first in Django, but this seems more like a pure Python thing -- maybe the Django tag isn't really appropriate.Impious
I don't see any import statements in __init__.py django 1.8. Was this for an older version? if so which version?Rubbico
Thanks for this question, it's pretty hard to find any advice on the real pros and cons of defining code in __init__.py. Unfortunately I still haven't found any solid answers on what can go wrong or what's best practice with putting code in __init__.py. One answer below suggested it's historical and a re-write would do it differently. I think that's my only take-away.Aletheaalethia
This question also has some relevant discussion: #1945069Aletheaalethia
some blog.pcarleton.com/post/python-init articles codingem.com/what-is-init-py-file-in-python on init.py realpython.com/lessons/package-initializationAletheaalethia
S
82

All imports in __init__.py are made available when you import the package (directory) that contains it.

Example:

./dir/__init__.py:

import something

./test.py:

import dir
# can now use dir.something

EDIT: forgot to mention, the code in __init__.py runs the first time you import any module from that directory. So it's normally a good place to put any package-level initialisation code.

EDIT2: dgrant pointed out to a possible confusion in my example. In __init__.py import something can import any module, not necessary from the package. For example, we can replace it with import datetime, then in our top level test.py both of these snippets will work:

import dir
print dir.datetime.datetime.now()

and

import dir.some_module_in_dir
print dir.datetime.datetime.now()

The bottom line is: all names assigned in __init__.py, be it imported modules, functions or classes, are automatically available in the package namespace whenever you import the package or a module in the package.

Sterlingsterlitamak answered 23/9, 2008 at 4:47 Comment(5)
Okay, thanks. But I'm still not sure why it would be a good idea to add classes to __init__.py I don't really consider these classes initialization code (but maybe I'm wrong about that).Nasa
These are probably the classes that are useful each time you work with the package. But I don't want to speculate, there could be many reasons why they are there, objective or not :)Sterlingsterlitamak
This can also be for historical reasons. When you are converting module to package, module.py to module/__init__.py all existing code can use it as before but now module can have submodules.Eupepsia
Modules execute parent __init__.py implicitly. By importing the modules inside __init__.py, you are creating cyclic imports. The __init__.py will not be executed fully before one such import. It is safer to keep __init__.py empty.Janson
It's important to remark that this is nothing specific to __init__.py files. If you had a file dir/other.py which had something like from datetime import datetime you would also be able to call dir.other.datetime.now() or even from dir.other import datetime.Compony
I
44

It's just personal preference really, and has to do with the layout of your python modules.

Let's say you have a module called erikutils. There are two ways that it can be a module, either you have a file called erikutils.py on your sys.path or you have a directory called erikutils on your sys.path with an empty __init__.py file inside it. Then let's say you have a bunch of modules called fileutils, procutils, parseutils and you want those to be sub-modules under erikutils. So you make some .py files called fileutils.py, procutils.py, and parseutils.py:

erikutils
  __init__.py
  fileutils.py
  procutils.py
  parseutils.py

Maybe you have a few functions that just don't belong in the fileutils, procutils, or parseutils modules. And let's say you don't feel like creating a new module called miscutils. AND, you'd like to be able to call the function like so:

erikutils.foo()
erikutils.bar()

rather than doing

erikutils.miscutils.foo()
erikutils.miscutils.bar()

So because the erikutils module is a directory, not a file, we have to define it's functions inside the __init__.py file.

In django, the best example I can think of is django.db.models.fields. ALL the django *Field classes are defined in the __init__.py file in the django/db/models/fields directory. I guess they did this because they didn't want to cram everything into a hypothetical django/db/models/fields.py model, so they split it out into a few submodules (related.py, files.py, for example) and they stuck the made *Field definitions in the fields module itself (hence, __init__.py).

Issacissachar answered 23/9, 2008 at 4:41 Comment(2)
dgrant, what I meant is that something can be an external module, dir.something will sill work. Thanks for the comment, I will edit my post to make it more clear.Sterlingsterlitamak
Do you know if this has been changed on python 3.10? i.e. I used to kept "miscutils" in __init__.py and call erikutils.foo() on python 3.8 but seems like I have to call erikutils.__init__.foo() on python 3.10.Eldoree
S
30

Using the __init__.py file allows you to make the internal package structure invisible from the outside. If the internal structure changes (e.g. because you split one fat module into two) you only have to adjust the __init__.py file, but not the code that depends on the package. You can also make parts of your package invisible, e.g. if they are not ready for general usage.

Note that you can use the del command, so a typical __init__.py may look like this:

from somemodule import some_function1, some_function2, SomeObject

del somemodule

Now if you decide to split somemodule the new __init__.py might be:

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2

From the outside the package still looks exactly as before.

Suttle answered 24/9, 2008 at 11:2 Comment(3)
@Arlen: The point is that it is not part of the public API. If you rename a module you can be sure that no dependent code breaks. In addition this ensures that the API elements only appear once, e.g., when introspection is used to automatically create API documentation.Suttle
@Arlen: Deleting a module prevents one from import <pack>.somemodule1 directly. You can only import from <pack> objects defined or imported in its __init__.py, and non-deleted submodules.Enchain
Good point pointing out the del option. Something to bear in mind if you want to clean up the namespace, although if you're doing so much in __init__.py that you have to clean up afterwards makes me thing you need another sub-module.Aletheaalethia
A
7

"We recommend not putting much code in an __init__.py file, though. Programmers do not expect actual logic to happen in this file, and much like with from x import *, it can trip them up if they are looking for the declaration of a particular piece of code and can't find it until they check __init__.py. "

-- Python Object-Oriented Programming Fourth Edition Steven F. Lott Dusty Phillips

Ardra answered 16/8, 2022 at 19:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.