Categories
module package python python-packaging

What is __init__.py for?

3267

What is __init__.py for in a Python source directory?

6

  • 36

    According to comment below by @Rob_before_edits and this stackoverflow thread 37139786, it seems that init.py is no longer needed for Python 3.3+.

    – Jun711

    May 15, 2018 at 22:13


  • 17

    Package without __init__ is namespace package, not a regular package. It’s not the same thing as @methane pointed out with an example here.

    – Catbuilts

    Jan 24, 2021 at 6:50


  • 1

    @Rainning A namespace package is not fundamentally different from a regular package. It is just a different way of creating packages. Once a namespace package is created, there is no functional difference between it and a regular package.

    – Jun711

    Sep 9, 2021 at 0:19

  • 1

    The official docs have a series of articles explain its usage, and they also defined every term precisely.

    – VimNing

    Sep 9, 2021 at 11:36

  • 1

    @Rainning maybe you didn’t realize that explanation I added above comes from pep420 verbatim

    – Jun711

    Sep 9, 2021 at 23:47

1850

It used to be a required part of a package (old, pre-3.3 “regular package”, not newer 3.3+ “namespace package”).

Here’s the documentation.

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__.py file. When a regular package is imported, this __init__.py file is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The __init__.py file 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.

4

  • 218

    What does this mean: “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”?

    – Carl G

    Jan 25, 2014 at 4:43

  • 118

    @CarlG Python searches a list of directories to resolve names in, e.g., import statements. Because these can be any directory, and arbitrary ones can be added by the end user, the developers have to worry about directories that happen to share a name with a valid Python module, such as ‘string’ in the docs example. To alleviate this, it ignores directories which do not contain a file named _ _ init _ _.py (no spaces), even if it is blank.

    Mar 7, 2014 at 20:56

  • 236

    @CarlG Try this. Make a directory called ‘datetime’ and in it make two blank files, the init.py file (with underscores) and datetime.py. Now open an interpreter, import sys, and issue sys.path.insert(0, '/path/to/datetime'), replacing that path with the path to whatever directory you just made. Now try something like from datetime import datetime;datetime.now(). You should get an AttributeError (because it is importing your blank file now). If you were to repeat these steps without creating the blank init file, this would not happen. That’s what it’s intended to prevent.

    Mar 7, 2014 at 21:03

  • 1

    All I get is ImportError: attempted relative import with no known parent package. My structure: /PyToHtml init.py pytohtml.py test.py where test.py has: from .pytohtml import HTML

    May 11 at 13:20


1121

Files named __init__.py are used to mark directories on disk as Python package directories.
If you have the files

mydir/spam/__init__.py
mydir/spam/module.py

and mydir is on your path, you can import the code in module.py as

import spam.module

or

from spam import module

If you remove the __init__.py file, Python will no longer look for submodules inside that directory, so attempts to import the module will fail.

The __init__.py file is usually empty, but can be used to export selected portions of the package under more convenient name, hold convenience functions, etc.
Given the example above, the contents of the init module can be accessed as

import spam

based on this

3

  • 147

    Update: The file __init__.py was required under Python 2.X and is still required under Python 2.7.12 (I tested it) but it is no longer required from (allegedly) Python 3.3 onwards, and is not required under Python 3.4.3 (I tested it). See stackoverflow.com/questions/37139786 for more details.

    Oct 30, 2016 at 14:49

  • 2

    Why do you have import spam inside` init.py`, what’s its help

    – alper

    Oct 17, 2021 at 11:47

  • @alper he doesn’t have import spam inside __init__.py, he has it inside main.py or whatever file needs to import the contents of spam. You can treat spam as an object you import and use functions defined within spam/__init__.py

    Apr 26 at 14:20

611

In addition to labeling a directory as a Python package and defining __all__, __init__.py allows you to define any variable at the package level. Doing so is often convenient if a package defines something that will be imported frequently, in an API-like fashion. This pattern promotes adherence to the Pythonic “flat is better than nested” philosophy.

An example

Here is an example from one of my projects, in which I frequently import a sessionmaker called Session to interact with my database. I wrote a “database” package with a few modules:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

My __init__.py contains the following code:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Since I define Session here, I can start a new session using the syntax below. This code would be the same executed from inside or outside of the “database” package directory.

from database import Session
session = Session()

Of course, this is a small convenience — the alternative would be to define Session in a new file like “create_session.py” in my database package, and start new sessions using:

from database.create_session import Session
session = Session()

Further reading

There is a pretty interesting reddit thread covering appropriate uses of __init__.py here:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

The majority opinion seems to be that __init__.py files should be very thin to avoid violating the “explicit is better than implicit” philosophy.

3

  • 7

    engine, sessionmaker, create_engine, and os can all also be imported from database now… seems like you’ve made a mess of that namespace.

    Sep 23, 2015 at 19:28

  • 15

    @ArtOfWarfare, you can use __all__ = [...] to limit what gets imported with import *. But aside from that, yes, you’re left with a messy top-level namespace.

    Sep 23, 2015 at 23:28

  • 3

    @NathanGould you could also use single leading underscore variables which are not imported by import * by default. Eg: import os as _os and use _os inside the __init__.py module in place of os.

    Jul 23, 2021 at 8:47