What is __init__.py for in a Python source directory?
It used to be a required part of a package (old, pre-3.3 "regular package", not newer 3.3+ "namespace package").
Python defines two types of packages, regular packages and namespace packages. Regular packages are traditional packages as they existed in Python 3.2 and earlier. A regular package is typically implemented as a directory containing an
__init__.pyfile. When a regular package is imported, this__init__.pyfile is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The__init__.pyfile can contain the same Python code that any other module can contain, and Python will add some additional attributes to the module when it is imported.
But just click the link, it contains an example, more information, and an explanation of namespace packages, the kind of packages without __init__.py.
The __init__.py file makes Python treat directories containing it as modules.
Furthermore, this is the first file to be loaded in a module, so you can use it to execute code that you want to run each time a module is loaded, or specify the submodules to be exported.
Since Python 3.3, __init__.py is no longer required to define directories as importable Python packages.
Check PEP 420: Implicit Namespace Packages:
Native support for package directories that don’t require
__init__.pymarker files and can automatically span multiple path segments (inspired by various third party approaches to namespace packages, as described in PEP 420)
Here's the test:
$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3
>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module
$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3
>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module
references:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Is __init__.py not required for packages in Python 3?
Although Python works without an __init__.py file you should still include one.
It specifies that the directory should be treated as a package, so therefore include it (even if it is empty).
There is also a case where you may actually use an __init__.py file:
Imagine you had the following file structure:
main_methods
|- methods.py
And methods.py contained this:
def foo():
return 'foo'
To use foo() you would need one of the following:
from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()
Maybe there you need (or want) to keep methods.py inside main_methods (runtimes/dependencies for example) but you only want to import main_methods.
If you changed the name of methods.py to __init__.py then you could use foo() by just importing main_methods:
import main_methods
print(main_methods.foo()) # Prints 'foo'
This works because __init__.py is treated as part of the package.
Some Python packages actually do this. An example is with JSON, where running import json is actually importing __init__.py from the json package (see the package file structure here):
Source code:
Lib/json/__init__.py
It facilitates importing other python files. When you placed this file in a directory (say stuff)containing other py files, then you can do something like import stuff.other.
root\
stuff\
other.py
morestuff\
another.py
Without this __init__.py inside the directory stuff, you couldn't import other.py, because Python doesn't know where the source code for stuff is and unable to recognize it as a package.
An __init__.py file makes imports easy. When an __init__.py is present within a package, function a() can be imported from file b.py like so:
from b import a
Without it, however, you can't import directly. You have to amend the system path:
import sys
sys.path.insert(0, 'path/to/b.py')
from b import a
One thing __init__.py allows is converting a module to a package without breaking the API or creating extraneous nested namespaces or private modules*. This helps when I want to extend a namespace.
If I have a file util.py containing
def foo():
...
then users will access foo with
from util import foo
If I then want to add utility functions for database interaction, and I want them to have their own namespace under util, I'll need a new directory**, and to keep API compatibility (so that from util import foo still works), I'll call it util/. I could move util.py into util/ like so,
util/
__init__.py
util.py
db.py
and in util/__init__.py do
from util import *
but this is redundant. Instead of having a util/util.py file, we can just put the util.py contents in __init__.py and the user can now
from util import foo
from util.db import check_schema
I think this nicely highlights how a util package's __init__.py acts in a similar way to a util module
* this is hinted at in the other answers, but I want to highlight it here
** short of employing import gymnastics. Note it won't work to create a new package with the same name as the file, see this
If you're using Python 2 and want to load siblings of your file you can simply add the parent folder of your file to your system paths of the session. It will behave about the same as if your current file was an init file.
import os
import sys
dir_path = os.path.dirname(__file__)
sys.path.insert(0, dir_path)
After that regular imports relative to the file's directory will work just fine. E.g.
import cheese
from vehicle_parts import *
# etc.
Generally you want to use a proper init.py file instead though, but when dealing with legacy code you might be stuck with f.ex. a library hard-coded to load a particular file and nothing but. For those cases this is an alternative.
init.py : It is a python file found in a package directory, it is invoked when the package or a module in the package is imported. You can use this to execute package initialization code, i.e. whenever the package is imported the python statements are executed first before the other modules in this folder gets executed. It is similar to main function of c or java program but this exists in the python package module(folder) rather than in the core python file. also it has access to global variables defined in this init.py file as when the module is imported into python file.
for eg. I have a init.py file in a folder called pymodlib, this file contains the following statements:
print(f'Invoking init.py for {name}') pystructures = ['for_loop', 'while__loop', 'ifCondition']
when I import this package "pymodlib" in the my solution module or notebook or python console: this two statements gets executed while importing. So in the log or console you would see the following output:
import pymodlib Invoking init.py for pymodlib
in the next statement of python console: I can access the global variable:
pymodlib.pystructures it gives the following output:
['for_loop', 'while__loop', 'ifCondition']
Now from python3.3 onwards the use of this file has been optional to make folder a python module. So you skip from including it in the python module folder.